回滚莫队初步

正常莫队,时间复杂度的保证来源于分块和每次挪动指针的$O(1)$或$O(log)$的修改。

然而像可持续化并查集的思想一样,在某些题中因为题目要求,导致并查集不能路径压缩,而要把时间版本存到栈,弹栈回溯时间版本。

有些题在适应题目中发现,只有扩展区间/缩小区间的时间复杂度有保证,那么就轮到回滚莫队解决问题。

实现流程及复杂度分析(那扩展区间为例):

1>左端点按块,右端点按大小排序

2>枚举每一个块,统计左端点在这个块里的答案,具体分两种情况:

  $[1]$:右端点也在块内,那么直接暴扫,扫一次$O(sqrt{N})$

  $[2]$:右端点不在,i因为排序右端点递增,所以维护一个右端点指针,每次右端点增加,因为左端点无序,所以每次都把左端点的操作存到栈内,每次都清空,所有右端点移动$O(N)$,左端点移动一次$O(sqrt{N})$

例题:

permu

数据范围较小,可以莫队+线段树水过

也可以在值域上维护链表,发现每次扩展区间可以$O(1)$,缩小区间几乎退化成暴力,应用回滚莫队。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<vector>
  6 #define MAXN 100010
  7 using namespace std;
  8 inline int maxn(int a,int b){return a>b?a:b; }
  9 inline int minn(int a,int b){return a<b?a:b; }
 10 inline int read(){
 11     int s=0,w=0;char ch=getchar();
 12     while(ch<'0'||ch>'9')w|=(ch=='-'),ch=getchar();
 13     while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
 14     return w?-s:s;
 15 }
 16 #define kd (read())
 17 int n,m,a[MAXN];
 18 int lef[MAXN],rig[MAXN];
 19 int bsize;
 20 inline int blk(int x){
 21     return (x-1)/bsize+1;
 22 }
 23 struct node{
 24     int l,r,id;
 25     friend bool operator <(const node &a,const node &b){
 26         if(blk(a.l)==blk(b.l))return a.r<b.r;
 27         else return blk(a.l)<blk(b.l);
 28     }
 29 }Q[MAXN];
 30 int zui[MAXN];
 31 struct rr{
 32     int opt,zhi;
 33     int zuo,you;
 34 };
 35 vector<rr >dd;
 36 int tong[MAXN];
 37 int main(){
 38     //freopen("da.in","r",stdin);
 39     //freopen("3.out","w",stdout);
 40     n=kd;m=kd;
 41     bsize=sqrt(n);
 42     for(int i=1;i<=n;++i)a[i]=kd;
 43     for(int i=1;i<=m;++i)Q[i].l=kd,Q[i].r=kd,Q[i].id=i;
 44     sort(Q+1,Q+m+1);
 45     //for(int i=1;i<=m;++i)
 46     //    cout<<Q[i].l<<" "<<Q[i].r<<endl;
 47     int pos=1;
 48     for(int i=1;i<=blk(n);++i){
 49         int r=i*bsize,lans=0;
 50         //cout<<"CCC"<<endl;
 51         while(pos<=m&&Q[pos].l<=i*bsize){
 52             //cout<<pos<<endl;
 53             if(Q[pos].r<=i*bsize){
 54                 //cout<<"qaq "<<pos<<endl;
 55                 //cout<<Q[pos].l<<" "<<Q[pos].r<<" "<<Q[pos].id<<endl;
 56                 for(int s=Q[pos].l;s<=Q[pos].r;++s){
 57                     tong[a[s]]=1;
 58                     if(tong[a[s]-1]&&tong[a[s]+1]){
 59                         rig[lef[a[s]-1]]=rig[a[s]+1];
 60                         lef[rig[a[s]+1]]=lef[a[s]-1];
 61                         zui[Q[pos].id]=maxn(zui[Q[pos].id],rig[a[s]+1]-lef[a[s]-1]+1);
 62                     }
 63                     else if(!tong[a[s]-1]&&!tong[a[s]+1]){
 64                         lef[a[s]]=a[s],rig[a[s]]=a[s];
 65                         zui[Q[pos].id]=maxn(zui[Q[pos].id],1);
 66                     }
 67                     else if(tong[a[s]-1]&&!tong[a[s]+1]){
 68                         rig[lef[a[s]-1]]=a[s];
 69                         lef[a[s]]=lef[a[s]-1];
 70                         zui[Q[pos].id]=maxn(zui[Q[pos].id],a[s]-lef[a[s]-1]+1);
 71                     }
 72                     else{
 73                         lef[rig[a[s]+1]]=a[s];
 74                         rig[a[s]]=rig[a[s]+1];
 75                         zui[Q[pos].id]=maxn(zui[Q[pos].id],rig[a[s]+1]-a[s]+1);
 76                     }
 77                 }
 78                 for(int s=Q[pos].l;s<=Q[pos].r;++s)tong[a[s]]=lef[a[s]]=rig[a[s]]=0;
 79                 ++pos;
 80             }
 81             else{
 82                 //cout<<"qwq "<<pos<<endl;
 83                 //cout<<Q[pos].l<<" "<<Q[pos].r<<" "<<Q[pos].id<<endl;
 84                 while(r<Q[pos].r){
 85                     ++r;
 86                     tong[a[r]]=1;
 87                     if(tong[a[r]-1]&&tong[a[r]+1]){
 88                         rig[lef[a[r]-1]]=rig[a[r]+1];
 89                         lef[rig[a[r]+1]]=lef[a[r]-1];
 90                         lans=maxn(lans,rig[a[r]+1]-lef[a[r]-1]+1);
 91                     }
 92                     else if(!tong[a[r]-1]&&!tong[a[r]+1]){
 93                         lef[a[r]]=a[r],rig[a[r]]=a[r];
 94                         lans=maxn(lans,1);
 95                     }
 96                     else if(tong[a[r]-1]&&!tong[a[r]+1]){
 97                         rig[lef[a[r]-1]]=a[r];
 98                         lef[a[r]]=lef[a[r]-1];
 99                         lans=maxn(lans,a[r]-lef[a[r]-1]+1);
100                     }
101                     else{
102                         lef[rig[a[r]+1]]=a[r];
103                         rig[a[r]]=rig[a[r]+1];
104                         lans=maxn(lans,rig[a[r]+1]-a[r]+1);
105                     }
106                 }
107                 int l=i*bsize+1;
108                 int tmp=lans;
109                 rr tt;
110                 while(l>Q[pos].l){
111                     --l;
112                     tong[a[l]]=1;
113                     tt.zhi=a[l];
114                     if(tong[a[l]-1]&&tong[a[l]+1]){
115                         rig[lef[a[l]-1]]=rig[a[l]+1];
116                         lef[rig[a[l]+1]]=lef[a[l]-1];
117                         lans=maxn(lans,rig[a[l]+1]-lef[a[l]-1]+1);
118                         tt.opt=1;
119                         tt.zuo=lef[a[l]-1];
120                         tt.you=rig[a[l]+1];
121                         dd.push_back(tt);
122                     }
123                     else if(!tong[a[l]-1]&&!tong[a[l]+1]){
124                         lef[a[l]]=a[l],rig[a[l]]=a[l];
125                         lans=maxn(lans,1);
126                         tt.opt=2;
127                         dd.push_back(tt);
128                     }
129                     else if(tong[a[l]-1]&&!tong[a[l]+1]){
130                         rig[lef[a[l]-1]]=a[l];
131                         lef[a[l]]=lef[a[l]-1];
132                         lans=maxn(lans,a[l]-lef[a[l]-1]+1);
133                         tt.opt=3;
134                         tt.zuo=lef[a[l]-1];
135                         dd.push_back(tt);
136                     }
137                     else{
138                         lef[rig[a[l]+1]]=a[l];
139                         rig[a[l]]=rig[a[l]+1];
140                         lans=maxn(lans,rig[a[l]+1]-a[l]+1);
141                         tt.opt=4;
142                         tt.you=rig[a[l]+1];
143                         dd.push_back(tt);
144                     }
145                 }
146                 zui[Q[pos].id]=lans;
147                 lans=tmp;
148                 while(!dd.empty()){
149                     tt=dd[dd.size()-1];
150                     if(tt.opt==1){
151                         tong[tt.zhi]=0;
152                         rig[tt.zuo]=tt.zhi-1;
153                         lef[tt.you]=tt.zhi+1;
154                     }
155                     else if(tt.opt==2){
156                         tong[tt.zhi]=0;
157                     }
158                     else if(tt.opt==3){
159                         tong[tt.zhi]=0;
160                         rig[tt.zuo]=tt.zhi-1;
161                     }
162                     else{
163                         tong[tt.zhi]=0;
164                         lef[tt.you]=tt.zhi+1;
165                     }
166                     dd.pop_back();
167                 }
168                 ++pos;
169             }
170         }
171         for(int i=1;i<=n;++i)tong[a[i]]=lef[a[i]]=rig[a[i]]=0;
172     }
173     for(int i=1;i<=m;++i)printf("%d
",zui[i]);
174     return 0;
175 }
因为不想思考而分情况讨论的大模拟码量
原文地址:https://www.cnblogs.com/2018hzoicyf/p/11663897.html