这才是真正的$Nsqrt{N}$吧$qwq$
记录每个数$vl$出现的位置$s[vl]$,和每个数$a[i]=vl$是第几个$vl$,记为$P[i]$,然后预处理出块$[i,j]$区间的答案$f[i][j]$;
对于$[l,r]$,现将$ans$设为$[l,r]$中整块的答案;对于散块,将散块中的每个数$a[i]=vl$,有对应的$P[i]$,我们用$s[vl]$检查第$P[i]+ans+1$个$vl$对应的位置是否在$[l,r]$,如果在的话就更新答案$ans=ans+1$,并重复上述过程,直到$P[i]+ans+1$不在$[l,r]$中。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cctype> #include<cstdlib> #include<vector> #include<queue> #include<map> #include<set> #define ull unsigned long long #define ll long long #define R register int #define pause (for(R i=1;i<=10000000000;++i)) #define OUT freopen("out.out","w",stdout); using namespace std; namespace Fread { static char B[1<<15],*S=B,*D=B; #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++) inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } inline bool isempty(const char& ch) {return ch<=36||ch>=127;} inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));} }using Fread::g; using Fread::gs; const int N=500010,M=710; int n,m,T,tot,lst; int cnt[N],pos[N],P[N],a[N],b[N],f[M][M]; vector <int> s[N]; #define pb push_back signed main() { n=g(),m=g(),T=pow(n,1/2.0); for(R i=1;i<=n;++i) a[i]=g(); memcpy(b,a,sizeof(int)*(n+1)); sort(b+1,b+n+1); tot=unique(b+1,b+n+1)-b-1; for(R i=1;i<=n;++i) a[i]=lower_bound(b+1,b+tot+1,a[i])-b; for(R i=1;i<=n;++i) s[a[i]].pb(i); for(R i=1;i<=n;++i) P[i]=++cnt[a[i]]-1; memset(cnt,0,sizeof(cnt)); for(R i=1;i<=n;++i) pos[i]=(i-1)/T+1; for(R p=1,L=pos[n],mx=0;p<=L;++p,mx=0,memset(cnt,0,sizeof(cnt))) for(R t=p;t<=L;++t) { for(R i=(t-1)*T+1,LL=min(t*T,n);i<=LL;++i) mx=max(++cnt[a[i]],mx); f[p][t]=mx; } for(R i=1,l,r;i<=m;++i) { R ans=0; l=g()^lst,r=g()^lst; if(pos[l]==pos[r]) { for(R i=l;i<=r;++i) ans=max(ans,++cnt[a[i]]); for(R i=l;i<=r;++i) cnt[a[i]]=0; } else { R p=pos[l]+1,q=pos[r]-1; ans=f[p][q]; for(R i=l,L=pos[l]*T;i<=L;++i) { R tmp=P[i]; while((tmp+ans)<s[a[i]].size()&&s[a[i]][tmp+ans]<=r) ++ans; } for(R i=q*T+1;i<=r;++i) { R tmp=P[i]; while((tmp-ans)>=0&&s[a[i]][tmp-ans]>=l) ++ans; } } printf("%d ",lst=ans); } }
2019.07.03