[BZOJ3595][SCOI2014]方伯伯的OJ(裂点Splay)

用一棵Splay按名次维护每个点,其中一个节点对应初始编号连续的一段区间,这样总节点数是$O(m)$的。

对每个编号记录这个点被Splay的那个节点维护,用std::map存储,只记录被修改的点。

每次删除时将一个点分裂成[l,k-1],k,[k+1,r]三个点(特判k=l或k=r),再删除k。

注意各种细节。

  1 #include<map>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  5 using namespace std;
  6 
  7 const int N=400010;
  8 int n,m,rt,nd,ans,op,x,y,L[N],R[N],len[N],f[N],ch[N][2];
  9 map<int,int>mp;
 10 
 11 int get(int l,int r){ nd++; L[nd]=l; R[nd]=r; len[nd]=r-l+1; return nd; }
 12 void upd(int x){ len[x]=len[ch[x][0]]+len[ch[x][1]]+R[x]-L[x]+1; }
 13 
 14 void rot(int &rt,int x){
 15     int y=f[x],z=f[y],w=ch[y][1]==x;
 16     if (rt==y) rt=x; else ch[z][ch[z][1]==y]=x;
 17     f[x]=z; f[y]=x; f[ch[x][w^1]]=y;
 18     ch[y][w]=ch[x][w^1]; ch[x][w^1]=y; upd(y);
 19 }
 20 
 21 void splay(int &rt,int x){
 22     while (x!=rt){
 23         int y=f[x],z=f[y];
 24         if (y!=rt) ((ch[z][0]==y)^(ch[y][0]==x)) ? rot(rt,x) : rot(rt,y);
 25         rot(rt,x);
 26     }
 27     upd(x);
 28 }
 29 
 30 int split(int x,int k){
 31     int y=get(k+1,R[x]); R[x]=k;
 32     if (!ch[x][1]) ch[x][1]=y,f[y]=x;
 33     else{
 34         int s=ch[x][1];
 35         while (ch[s][0]) s=ch[s][0];
 36         ch[s][0]=y; f[y]=s;
 37     }
 38     splay(rt,y); mp[R[x]]=x; mp[R[y]]=y; return y;
 39 }
 40 
 41 void Split(int &x,int k){
 42     if (k<R[x]) split(x,k);
 43     if (k>L[x]) x=split(x,k-1);
 44     splay(rt,x);
 45 }
 46 
 47 void ins1(int x){
 48     int s=rt;
 49     while (ch[s][0]) s=ch[s][0];
 50     ch[s][0]=x; f[x]=s; splay(rt,x);
 51 }
 52 
 53 void ins2(int x){
 54     int s=rt;
 55     while (ch[s][1]) s=ch[s][1];
 56     ch[s][1]=x; f[x]=s; splay(rt,x);
 57 }
 58 
 59 void del(int x){
 60     splay(rt,x);
 61     int ls=ch[x][0],rs=ch[x][1];
 62     f[ls]=f[rs]=0; ch[x][0]=ch[x][1]=0;
 63     if (!ls || !rs) { rt=ls+rs; return; }
 64     int s=ls; while (ch[s][1]) s=ch[s][1];
 65     splay(ls,s); ch[s][1]=rs; f[rs]=rt=s; upd(s);
 66 }
 67 
 68 int find(int k){
 69     for (int x=rt; ; ){
 70         if (k<=len[ch[x][0]]) x=ch[x][0];
 71         else{
 72             k-=len[ch[x][0]];
 73             if (k<=R[x]-L[x]+1) return k+L[x]-1;
 74             else k-=R[x]-L[x]+1,x=ch[x][1];
 75         }
 76     }
 77 }
 78 
 79 int main(){
 80     freopen("bzoj3595.in","r",stdin);
 81     freopen("bzoj3595.out","w",stdout);
 82     scanf("%d%d",&n,&m); rt=get(1,n); mp[n]=1;
 83     rep(i,1,m){
 84         scanf("%d%d",&op,&x); x-=ans;
 85         if (op==1){
 86             scanf("%d",&y); y-=ans;
 87             int t=mp.lower_bound(x)->second;
 88             Split(t,x); printf("%d\n",ans=len[t]-len[ch[t][1]]);
 89             L[t]=R[t]=y; mp[y]=t;
 90         }
 91         if (op==2){
 92             int t=mp.lower_bound(x)->second;
 93             Split(t,x); printf("%d\n",ans=len[t]-len[ch[t][1]]);
 94             del(t); ins1(t);
 95         }
 96         if (op==3){
 97             int t=mp.lower_bound(x)->second;
 98             Split(t,x); printf("%d\n",ans=len[t]-len[ch[t][1]]);
 99             del(t); ins2(t);
100         }
101         if (op==4) printf("%d\n",ans=find(x));
102     }
103     return 0;
104 }

 

posted @ 2018-12-28 18:46  HocRiser  阅读(175)  评论(0编辑  收藏  举报