题目大意是给出一个非降序排列的数组,然后n个询问,每次询问一个区间内出现次数最多的数的次数。
首先要弄清楚题目的是一个非降序的数组,那么说明相等的数都会在一起,类似于11223334569这样的,那么可以将其合并,由于这种多次区间询问的题一般用
到的是线段树或者RMQ,所以就往这方面去靠,用num[i]和cont[i]表示第i段的数值和出现的次数,val[i]表示位置i所在段的编号,lef[i]和ri[i]表示位置i所在段的左右端点
位置,那么对于每次查询(l,r)区间就分成了三段,ri[l]-l+1,r-lef[r]+1和中间一段,而中间的一段就完全是根据cont数组求的RMQ问题,然后三者取大的就好。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int M = 1e5 + 10; 8 int a[M],d[M][20],cont[M],num[M]; 9 int lef[M],ri[M],val[M]; 10 int max(int x,int y) {return x>y?x:y;} 11 12 void rmq(int x) 13 { 14 for (int i=1 ; i<=x ; i++) d[i][0]=cont[i]; 15 for (int j=1 ; (1<<j)<=x ; j++) 16 for (int i=0 ; i+(1<<j)-1<x ; i++) 17 d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]); 18 } 19 20 int rmq(int l,int r) 21 { 22 if (l>r) return 0; 23 int k=0; 24 while ((1<<(k+1))<=r-l+1) k++; 25 return max(d[l][k],d[r-(1<<k)+1][k]); 26 } 27 28 int main() 29 { 30 int n,q,i; 31 while (~scanf("%d",&n)&&n){ 32 scanf("%d",&q); 33 for (i=1 ; i<=n ; i++) scanf("%d",a+i); 34 int ans=-M,j=1; 35 memset(cont,0,sizeof(cont)); 36 for (i=1 ; i<=n ; i++) 37 { 38 if (a[i]!=ans) 39 { 40 val[j]=a[i]; 41 ans=a[i]; 42 int k=i,w=i; 43 while (ans==a[i]){ 44 cont[j]++; 45 i++; 46 } 47 i--; 48 for ( ; k<=i ; k++) 49 { 50 num[k]=j; 51 lef[k]=w; 52 ri[k]=i; 53 } 54 j++; 55 } 56 } 57 j--; 58 rmq(j); 59 int l,r; 60 /* for (i=1 ; i<=j ; i++) cout<<val[i]<<" "; 61 cout<<endl; 62 for (i=1 ; i<=j ; i++) cout<<cont[i]<<" "; 63 cout<<endl; 64 for (i=1 ; i<=n ; i++) cout<<num[i]<<" "; 65 cout<<endl; 66 for (i=1 ; i<=n ; i++) cout<<lef[i]<<" "; 67 cout<<endl; 68 for (i=1 ; i<=n ; i++) cout<<ri[i]<<" "; 69 cout<<endl;*/ 70 while (q--) 71 { 72 scanf("%d%d",&l,&r); 73 if (num[l]==num[r]) 74 { 75 printf("%d\n",r-l+1); 76 continue; 77 } 78 printf("%d\n",max(r-lef[r]+1,max(rmq(num[ri[l]+1],num[lef[r]-1]),ri[l]-l+1))); 79 80 } 81 } 82 return 0; 83 }