Codeforces Round #209 (Div. 2) D:http://codeforces.com/contest/359/problem/D
题意:给以一个n个数的序列,然后问你最大的区间l,r,在这个区间里面,存在一个数是这个区间所有数的约数,如果这个区间有多个,统计有多少个以及每个区间的左端点。
题解:这一题,别人用了一个很特殊的找发,让我叹为观止。哎,没有数学功底以及很强的推理能力,真的有点力不从心啊。说说别人是怎么找的吧。首先,从第一个数开始,往右边找,然后找到第一个不是a[1]倍数的数,这是第一个区间,然后从这个数让左边找,找到以这个数为约数的左边全歼,然后往右边找,找到不是这个数的倍数的那个数,并把这个数放进队列,因为这个数就是下一次要开始找的数,对于当前这个数,就会得到一个区间,然后进行相关的更新。接着又从队列中数,然后重复上面的 数,直到最后一个数。这里,别人的证明就是每个数最多被找logn次,自己画画图,好像是这样。所以复杂度就是nlogn.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int N=3e5+10; 8 int a[N],n; 9 int ans[N],top; 10 int anss; 11 int main(){ 12 while(~scanf("%d",&n)){ 13 memset(ans,0,sizeof(ans)); 14 memset(a,0,sizeof(a)); 15 for(int i=1;i<=n;i++) 16 scanf("%d",&a[i]); 17 queue<int>Q; 18 anss=0;top=0; 19 Q.push(1); 20 while(!Q.empty()){ 21 int x=Q.front(); 22 Q.pop(); 23 int num=1,ps=0; 24 for(int i=x-1;i>=1;i--){ 25 if(a[i]%a[x]==0){ 26 num++; 27 } 28 else 29 break; 30 } 31 ps=x-num+1; 32 for(int i=x+1;i<=n;i++){ 33 if(a[i]%a[x]==0) 34 num++; 35 else{ 36 Q.push(i); 37 break; 38 } 39 } 40 if(num>anss){ 41 anss=num;top=0; 42 ans[++top]=ps; 43 } 44 else if(num==anss) 45 ans[++top]=ps; 46 } 47 printf("%d %d ",top,anss-1); 48 for(int i=1;i<=top;i++){ 49 if(i==top)printf("%d ",ans[i]); 50 else 51 printf("%d ",ans[i]); 52 } 53 } 54 }