【模板】【回滚莫队】洛谷p5906
回滚莫队就是在莫队的基础上加上回滚操作,右端点单调往右移动,左端点每次从块的最右端(br)移到询问的r , 再直接移动回来br,保存 [ br , r ] 的信息,移动到 [ l , r ] 后 直接回滚到 [br , r ] 继续进行上述操作
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 2e5+9; 4 struct Que{ 5 int l,r,lid; 6 int id,ans; 7 }q[N]; 8 int num[N],mx[N],mi[N],las_mx[N],las_mi[N],blo[N]; 9 int calmi[N]; 10 int a[N]; 11 int n,m; 12 bool cmp(Que a,Que b){ 13 if(a.lid == b.lid ) return a.r < b.r; 14 return a.lid < b.lid; 15 } 16 bool cmpid(Que a,Que b){ 17 return a.id < b.id; 18 } 19 int cal(int le,int ri){ 20 int res = 0; 21 for(int i = le;i<=ri;++i){ 22 if(!calmi[a[i]]) calmi[a[i]] = i; 23 else res = max(res,i - calmi[a[i]]); 24 } 25 for(int i = le;i<=ri;++i) calmi[a[i]] = 0; 26 return res; 27 } 28 void Mo(){ 29 sort(q+1,q+1+m,cmp); 30 int len = sqrt(n); 31 int qid = 1,bid = q[1].lid; 32 for(;bid<=blo[n];++bid){ 33 int br = min( n,bid * len); 34 int le = br+1,ri = le-1; 35 int cur_ans = 0,las_ans = 0; 36 vector<int> r_use; 37 for(;q[qid].lid == bid;++qid){ 38 39 if( blo[ q[qid].r ] == bid){ 40 q[qid].ans = cal(q[qid].l,q[qid].r); 41 continue; 42 } 43 44 while(ri < q[qid].r ){ 45 ++ri; 46 r_use.push_back(a[ri]); 47 mx[ a[ri] ] = ri; 48 if(!mi[a[ri]]) mi[a[ri]] = ri; 49 cur_ans = max(cur_ans,ri - mi[a[ri]]); 50 las_mx[a[ri]] = mx[a[ri]]; 51 las_mi[a[ri]] = mi[a[ri]]; 52 } 53 las_ans = cur_ans; 54 vector<int> l_use; 55 while(le > q[qid].l){ 56 --le; 57 l_use.push_back(a[le]); 58 if(mx[a[le]]) cur_ans = max(cur_ans,mx[a[le]] - le); 59 else mx[a[le]] = le; 60 } 61 q[qid].ans = cur_ans; 62 cur_ans = las_ans; 63 for(auto it : l_use){ 64 mx[it] = las_mx[it]; 65 mi[it] = las_mi[it]; 66 } 67 le = br+1; 68 } 69 for(auto it : r_use) mx[it] = mi[it] = las_mx[it] = las_mi[it] = 0; 70 } 71 } 72 void init(){ 73 scanf("%d",&m); 74 int len = sqrt(n); 75 for(int i= 1;i<=n;++i) blo[i] = (i-1)/len + 1; 76 for(int i = 1;i<=m;++i){ 77 q[i].id = i; 78 scanf("%d %d",&q[i].l,&q[i].r); 79 q[i].lid = blo[ q[i].l ] ; 80 } 81 } 82 int main(){ 83 scanf("%d",&n); 84 int cnt = 0; 85 for(int i = 1;i<=n;++i){ 86 scanf("%d",a+i); 87 num[++cnt] = a[i]; 88 } 89 sort(num+1,num+1+cnt); 90 cnt = unique(num+1,num+1+cnt) - num - 1; 91 for(int i = 1;i<=n;++i) a[i] = lower_bound(num+1,num+1+cnt,a[i]) - num; 92 init(); 93 Mo(); 94 sort(q+1,q+1+m,cmpid); 95 for(int i = 1;i<=m;++i) printf("%d\n",q[i].ans); 96 return 0; 97 }