uva 11235
题解:整个数组是非降序的,所有相等元素都会聚集在一起。开一个num数组,用num[i]来记录第i段相等的元素有多少个(也就是说相当于RMQ中的元素值了),num数组的长度就是原数列不同元素的个数(段数),l数组记录i段元素的上界,r数组记录i段元素的下界,用一个mark数组记录i位置的元素属于第几段。假设询问区间为a,b:
L=mark[a],R=mark[b];
ans=max(r[L]-a+1,b-l[R]+1,夹在这两个段中最大值)
图解:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> using namespace std; int n,q,num[100010],mark[100010],l[100010],r[100010],pos,maxnum[100010][26]; void RMQ() { for(int i=1;i<=pos;i++) maxnum[i][0]=num[i]; for(int j=1;j<25;j++) { for(int i=1;i<n;i++) if(i+(1<<j)-1<=n) maxnum[i][j]=max(maxnum[i][j-1],maxnum[i+(1<<(j-1))][j-1]); } } int main() { while(scanf("%d",&n)!=EOF) { if(n==0) break; int x,val; scanf("%d",&q); pos=0; for(int i=1;i<=n;i++) { scanf("%d",&x); if(x==val) { num[pos]++; mark[i]=pos; } else { r[pos]=i-1; pos++; num[pos]=1; val=x; mark[i]=pos; l[pos]=i; } } r[pos]=n; RMQ(); while(q--) { int x,y,ans=0; scanf("%d%d",&x,&y); if(mark[x]==mark[y]) { printf("%d\n",y-x+1); continue; } if(mark[x]+1<=mark[y]-1) { int k=(int)(log(mark[y]-mark[x]-1)/log(2.0)); ans=max(maxnum[mark[x]+1][k],maxnum[mark[y]-(1<<k)][k]); } ans=max(ans,max(r[mark[x]]-x+1,y-l[mark[y]]+1)); printf("%d\n",ans); } } return 0; }