• 回滚莫队初步


    正常莫队,时间复杂度的保证来源于分块和每次挪动指针的$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 }
    因为不想思考而分情况讨论的大模拟码量
  • 相关阅读:
    LeetCode No41. 缺失的第一个正数
    LeetCode 面试题 01.05. 一次编辑
    LeetCode No45. 跳跃游戏 II
    LeetCode No436. 寻找右区间
    LeetCode No47. 全排列 II
    LeetCode No812. 最大三角形面积
    LeectCode No953. 验证外星语词典
    LeetCode No462. 最少移动次数使数组元素相等 II
    LeetCode No44. 通配符匹配
    LeetCode No43. 字符串相乘
  • 原文地址:https://www.cnblogs.com/2018hzoicyf/p/11663897.html
Copyright © 2020-2023  润新知