• 回滚莫队初步


    正常莫队,时间复杂度的保证来源于分块和每次挪动指针的$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 }
    因为不想思考而分情况讨论的大模拟码量
  • 相关阅读:
    javascript性能
    图片及js的预加载
    url参数解析
    javascript预编译
    13、MVC 设计思想
    12、JDBC 流程
    线程-2、sleep() 、join()、yield()有什么区别
    线程-1、创建线程的方式及实现
    集合-7、HashMap实现原理及源码分析
    集合-6、HashSet 和 HashMap 区别
  • 原文地址:https://www.cnblogs.com/2018hzoicyf/p/11663897.html
Copyright © 2020-2023  润新知