题意:小H是个善于思考的学生,现在她又在思考一个有关序列的问题。 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n)。
这个特殊区间满足,存在一个k(L <= k <= R),并且对于任意的i(L <= i <= R),ai都能被ak整除。这样的一个特殊区间 [L, R]价值为R – L。
小H想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些区间又分别是哪些呢?你能帮助她吧。
100%: 1 <= n <= 500000 , 1 <= ai < 2 ^ 31.
思路:
1 #include<map> 2 #include<set> 3 #include<cmath> 4 #include<cstdio> 5 #include<vector> 6 #include<cstring> 7 #include<cstdlib> 8 #include<iostream> 9 #include<algorithm> 10 #define MAXN 510000 11 using namespace std; 12 13 14 int f[MAXN][20],g[MAXN][20]; 15 int a[MAXN],b[MAXN],c[MAXN]; 16 int n,num; 17 18 int gcd(int x,int y) 19 { 20 int a,b,r,t; 21 a=x; b=y; 22 if(a<b){t=a;a=b;b=t;} 23 while(1) 24 { 25 r=a%b; 26 a=b; 27 b=r; 28 if(!r) break; 29 30 } 31 return a; 32 } 33 34 int query1(int x,int y) 35 { 36 int len,l; 37 len=y-x+1; l=log(len)/log(2); 38 return gcd(f[x][l],f[y-(1<<l)+1][l]); 39 } 40 41 int query2(int x,int y) 42 { 43 int len,l; 44 len=y-x+1; l=log(len)/log(2); 45 return min(g[x][l],g[y-(1<<l)+1][l]); 46 } 47 int isok(int k) 48 { 49 num=0; 50 for(int i=1;i+k-1<=n;i++) 51 { 52 int s1=query1(i,i+k-1); 53 int s2=query2(i,i+k-1); 54 if(s1==s2) b[++num]=i; 55 // printf("%d %d %d %d\n",i,i+k-1,s1,s2); 56 } 57 if(num) return 1; 58 else return 0; 59 } 60 int main() 61 { 62 freopen("1.in","r",stdin); 63 freopen("1.out","w",stdout); 64 scanf("%d",&n); 65 for(int i=1;i<=n;i++) 66 { 67 scanf("%d",&a[i]); 68 f[i][0]=g[i][0]=a[i]; 69 } 70 int len=log(n)/log(2); 71 for(int i=1;i<=len;i++) 72 for(int j=1;j+(1<<i)-1<=n;j++) 73 { 74 f[j][i]=gcd(f[j][i-1],f[j+(1<<(i-1))][i-1]); 75 g[j][i]=min(g[j][i-1],g[j+(1<<(i-1))][i-1]); 76 } 77 int l,r,mid,last,ans; 78 l=1;r=n;last=ans=1;c[1]=1; 79 while(l<=r) 80 { 81 int mid=(l+r)/2; 82 if(isok(mid)) 83 { 84 last=mid; ans=num; 85 for(int i=1;i<=num;i++) c[i]=b[i]; 86 l=mid+1; 87 } 88 else r=mid-1; 89 } 90 printf("%d %d\n",ans,last-1); 91 for(int i=1;i<=ans-1;i++) printf("%d ",c[i]); 92 printf("%d",c[ans]); 93 }
原文:https://www.cnblogs.com/myx12345/p/9270009.html