正常莫队,时间复杂度的保证来源于分块和每次挪动指针的$O(1)$或$O(log)$的修改。
然而像可持续化并查集的思想一样,在某些题中因为题目要求,导致并查集不能路径压缩,而要把时间版本存到栈,弹栈回溯时间版本。
有些题在适应题目中发现,只有扩展区间/缩小区间的时间复杂度有保证,那么就轮到回滚莫队解决问题。
实现流程及复杂度分析(那扩展区间为例):
1>左端点按块,右端点按大小排序
2>枚举每一个块,统计左端点在这个块里的答案,具体分两种情况:
$[1]$:右端点也在块内,那么直接暴扫,扫一次$O(sqrt{N})$
$[2]$:右端点不在,i因为排序右端点递增,所以维护一个右端点指针,每次右端点增加,因为左端点无序,所以每次都把左端点的操作存到栈内,每次都清空,所有右端点移动$O(N)$,左端点移动一次$O(sqrt{N})$
例题:
数据范围较小,可以莫队+线段树水过
也可以在值域上维护链表,发现每次扩展区间可以$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 }