1. 程式人生 > >[BZOJ3595][SCOI2014]方伯伯的OJ(裂點Splay)

[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 }