【题目描述】
给定一个序列,下标从0开始,分别为a0,a1,a2...an−1,有m个询问,每次给出l和r,求满足ai=aj且l<=i<=j<=r时j−i的最大值
本题强制在线,l和r均进行了加密,解密过程为
l′=min((l+ans)mod
r′=max((l+ans)mod
其中ans为上次答案
【输入格式】
第一行,两个正整数n,m
第二行,n个非负整数a0,a1,a2...an−1
以下m行,每行两个数l,r,表示询问
【输出格式】
m行,表示答案
【样例输入】
5 3 0 4 0 0 1 3 2 4 1 0 0
【样例输出】
1 2 0
0<=l,r<n
【来源】
国家集训队2015论文集
离线预处理+分块,复杂度有保障。
1 #include <cstdio> 2 const int N=100001,M=301,B=334; 3 int n,Q,lmn[N][M],rmx[N][M]; 4 int dp[M][M],a[N],bel[N]; 5 int fst[N][M],lst[N][M]; 6 int st[M],ed[M],tot; 7 int h[N],vis[N],tim; 8 char c;int x; 9 __inline int min(int x,int y){return x>y?y:x;} 10 __inline int max(int x,int y){return x<y?y:x;} 11 __inline int Read(){ 12 while(x=getchar()-48,x>9||x<0); 13 while(c=getchar()-48,c<=9&&c>=0)x=x*10+c; 14 return x; 15 } 16 int main(){ 17 freopen("easy_seq.in","r",stdin); 18 freopen("easy_seq.out","w",stdout); 19 scanf("%d%d",&n,&Q); 20 for(register int i=1;i<=n;i++)a[i]=Read(); 21 for(register int i=1;i<=n;i++)bel[i]=(i-1)/B+1; 22 for(register int i=1;i<=n;i++)ed[bel[i]]=i; 23 for(register int i=n;i>=1;i--)st[bel[i]]=i; 24 25 tot=bel[n]; 26 27 for(register int i=n;i>=1;i--)fst[a[i]][bel[i]]=i; 28 for(register int i=1;i<=n;i++)lst[a[i]][bel[i]]=i; 29 30 for(register int i=1;i<=n;i++){ 31 for(register int j=1;j<=bel[i];j++) 32 lmn[i][j]=fst[a[i]][j]; 33 for(register int j=bel[i];j<=tot;j++) 34 rmx[i][j]=lst[a[i]][j]; 35 } 36 37 for(register int i=1;i<=n;i++){ 38 for(register int j=bel[i]-1;j>=1;j--) 39 if(!lmn[i][j])lmn[i][j]=lmn[i][j+1]; 40 else lmn[i][j]=min(lmn[i][j],lmn[i][j+1]); 41 for(register int j=bel[i]+1;j<=tot;j++) 42 rmx[i][j]=max(rmx[i][j],rmx[i][j-1]); 43 } 44 45 for(register int j=1,i;j<=n;j++){i=bel[j]; 46 dp[i][i]=max(dp[i][i],lst[a[j]][i]-j); 47 dp[i][i]=max(dp[i][i],j-fst[a[j]][i]); 48 } 49 50 for(register int k=2;k<=tot;k++) 51 for(register int i=1,j;(j=i+k-1)<=tot;i++){ 52 dp[i][j]=max(dp[i][j-1],dp[i+1][j]); 53 for(register int t=st[i];t<=ed[i];t++) 54 dp[i][j]=max(dp[i][j],rmx[t][j]-t); 55 } 56 int l_,r_,l,r,ans=0; 57 while(Q--){ 58 l=Read();r=Read(); 59 l_=min((l+ans)%n,(r+ans)%n); 60 r_=max((l+ans)%n,(r+ans)%n); 61 l=l_+1;r=r_+1; 62 63 if(bel[l]==bel[r]){ 64 ++tim;ans=0; 65 for(register int i=l;i<=r;i++){ 66 if(vis[a[i]]!=tim){ 67 vis[a[i]]=tim; 68 h[a[i]]=i; 69 } 70 else ans=max(ans,i-h[a[i]]); 71 } 72 printf("%d ",ans); 73 continue; 74 } 75 76 if(st[bel[l]]!=l)l_=ed[bel[l]]+1;else l_=l; 77 if(ed[bel[r]]!=r)r_=st[bel[r]]-1;else r_=r; 78 79 ans=dp[bel[l_]][bel[r_]];++tim; 80 for(register int i=l;i<l_;i++){ 81 ans=max(ans,rmx[i][bel[r_]]-i); 82 if(vis[a[i]]!=tim){ 83 vis[a[i]]=tim; 84 h[a[i]]=i; 85 } 86 else ans=max(ans,i-h[a[i]]); 87 } 88 for(register int i=r_+1;i<=r;i++){ 89 if(!lmn[i][bel[l_]])lmn[i][bel[l_]]=n; 90 ans=max(ans,i-lmn[i][bel[l_]]); 91 if(vis[a[i]]!=tim){ 92 vis[a[i]]=tim; 93 h[a[i]]=i; 94 } 95 else ans=max(ans,i-h[a[i]]); 96 } 97 printf("%d ",ans); 98 } 99 return 0; 100 }