【bzoj 3595】: [Scoi2014]方伯伯的Oj
蒟蒻终于做到一道方伯伯的题了……
调了一个上午一直TLE(发现自己打了好久的splay板子竟然是错的这种丢人事情我就不说了)
很明显,要建两棵树,$T1$维护排名,$T2$维护编号,$T2$表示编号为$x$的点在$T1$中的节点编号
操作一:在$T2$中找到编号,到$T1$算排名,然后更新$T2$
其他操作类似
然后重点讲一下分点操作
因为只有$10^5$个操作,但却有$10^8$个点,所以不可能对每一个点都建树
于是我们考虑一下,让splay的每一个节点代表的不是点,而是一个区间。当需要用到点时,再把这个点从区间中分裂出来
这样可以保证不需要用到的节点不会影响复杂度
关于分点操作具体如何实现,可以参考代码
1 //minamoto 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int N=330005,INF=0x3f3f3f3f; 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<15,stdin),p1==p2)?EOF:*p1++) 6 char buf[1<<15],*p1=buf,*p2=buf; 7 inline int read(){ 8 #define num ch-'0' 9 char ch;bool flag=0;int res; 10 while(!isdigit(ch=getc())) 11 (ch=='-')&&(flag=true); 12 for(res=num;isdigit(ch=getc());res=res*10+num); 13 (flag)&&(res=-res); 14 #undef num 15 return res; 16 } 17 char obuf[1<<24],*o=obuf; 18 void print(int x){ 19 if(x>9) print(x/10); 20 *o++=x%10+48; 21 } 22 map<int,int> f;int n,m,ans; 23 struct node{ 24 int fa,ch[2]; 25 int sz,l,r; 26 } e[N]; 27 int cnt,root; 28 void pushup(int x){ 29 e[x].sz=e[e[x].ch[0]].sz+e[e[x].ch[1]].sz+e[x].r-e[x].l+1; 30 } 31 void rotate(int x){ 32 int y=e[x].fa,z=e[y].fa; 33 int op= e[y].ch[1]==x; 34 e[x].fa=z; 35 if(z) e[z].ch[e[z].ch[1]==y]=x; 36 e[y].ch[op]=e[x].ch[op^1],e[e[x].ch[op^1]].fa=y; 37 e[y].fa=x;e[x].ch[op^1]=y; 38 pushup(x),pushup(y); 39 } 40 void splay(int x,int goal){ 41 while(e[x].fa!=goal){ 42 int y=e[x].fa,z=e[y].fa; 43 if(z!=goal) 44 ((e[z].ch[0]==y)^(e[y].ch[0]==x))?rotate(x):rotate(y); 45 rotate(x); 46 } 47 pushup(x); 48 if(goal==0) root=x; 49 } 50 int query(int x){ 51 splay(x,0); 52 return e[x].sz-e[e[x].ch[1]].sz; 53 } 54 void pop(int x){ 55 int lower=e[x].ch[0]; 56 int upper=e[x].ch[1]; 57 while(e[lower].ch[1]) lower=e[lower].ch[1]; 58 while(e[upper].ch[0]) upper=e[upper].ch[0]; 59 if(!lower&&!upper) {root=0;return;} 60 if(!lower){ 61 splay(upper,0); 62 e[x].fa=e[upper].ch[0]=0; 63 e[x].sz=1,pushup(upper); 64 } 65 else if(!upper){ 66 splay(lower,0); 67 e[x].fa=e[lower].ch[1]=0; 68 e[x].sz=1,pushup(lower); 69 } 70 else{ 71 splay(lower,0),splay(upper,lower); 72 e[upper].ch[0]=e[x].fa=0; 73 e[x].sz=1; 74 pushup(upper),pushup(lower); 75 } 76 } 77 int getKth(int x){ 78 int now=root; 79 while(true){ 80 int sum=e[e[now].ch[0]].sz+e[now].r-e[now].l+1; 81 if(e[e[now].ch[0]].sz>=x) now=e[now].ch[0]; 82 else if(sum>=x){x-=e[e[now].ch[0]].sz;break;} 83 else x-=sum,now=e[now].ch[1]; 84 } 85 return e[now].l+x-1; 86 } 87 void push_front(int x){ 88 if(!root){root=x;return;} 89 int fa=root; 90 while(e[fa].ch[0]) e[fa].sz++,fa=e[fa].ch[0]; 91 e[fa].sz++; 92 e[fa].ch[0]=x,e[x].fa=fa; 93 splay(x,0); 94 } 95 void push_back(int x){ 96 if(!root){root=x;return;} 97 int fa=root; 98 while(e[fa].ch[1]) e[fa].sz++,fa=e[fa].ch[1]; 99 e[fa].sz++; 100 e[fa].ch[1]=x,e[x].fa=fa; 101 splay(x,0); 102 } 103 void split(int x,int id){ 104 int l=e[x].l,r=e[x].r,ls,rs; 105 if(l==r) return; 106 if(l==id){ 107 rs=++cnt; 108 f[r]=rs,f[id]=x; 109 e[rs].ch[1]=e[x].ch[1]; 110 e[e[rs].ch[1]].fa=rs; 111 e[x].ch[1]=rs,e[rs].fa=x; 112 e[rs].l=l+1,e[rs].r=r; 113 e[x].r=l; 114 pushup(rs),pushup(x); 115 } 116 else if(r==id){ 117 ls=++cnt; 118 f[r-1]=ls,f[id]=x; 119 e[ls].ch[0]=e[x].ch[0]; 120 e[e[ls].ch[0]].fa=ls; 121 e[x].ch[0]=ls,e[ls].fa=x; 122 e[ls].l=l,e[ls].r=r-1; 123 e[x].l=r; 124 pushup(ls),pushup(x); 125 } 126 else{ 127 ls=++cnt,rs=++cnt; 128 f[id]=x,f[id-1]=ls,f[r]=rs; 129 e[ls].ch[0]=e[x].ch[0],e[rs].ch[1]=e[x].ch[1]; 130 e[e[ls].ch[0]].fa=ls,e[e[rs].ch[1]].fa=rs; 131 e[x].ch[0]=ls,e[x].ch[1]=rs,e[ls].fa=x,e[rs].fa=x; 132 e[x].l=e[x].r=id; 133 e[ls].l=l,e[ls].r=id-1; 134 e[rs].l=id+1,e[rs].r=r; 135 pushup(ls),pushup(rs),pushup(x); 136 } 137 splay(x,0); 138 } 139 void init(){ 140 root=cnt=1; 141 e[1].l=1,e[1].r=n,e[1].sz=n; 142 f[n]=1; 143 } 144 int main(){ 145 //freopen("testdata.in","r",stdin); 146 n=read(),m=read(); 147 init(); 148 while(m--){ 149 int opt=read(); 150 switch(opt){ 151 case 1:{ 152 int oid=read()-ans,nid=read()-ans; 153 int x=f.lower_bound(oid)->second; 154 split(x,oid); 155 ans=query(x); 156 e[x].l=e[x].r=nid,f[nid]=x; 157 print(ans),*o++='\n'; 158 break; 159 } 160 case 2:{ 161 int id=read()-ans; 162 int x=f.lower_bound(id)->second; 163 split(x,id); 164 ans=query(x); 165 pop(x); 166 push_front(x); 167 print(ans),*o++='\n'; 168 break; 169 } 170 case 3:{ 171 int id=read()-ans; 172 int x=f.lower_bound(id)->second; 173 split(x,id); 174 ans=query(x); 175 pop(x); 176 push_back(x); 177 print(ans),*o++='\n'; 178 break; 179 } 180 case 4:{ 181 int k=read()-ans; 182 ans=getKth(k); 183 print(ans),*o++='\n'; 184 break; 185 } 186 } 187 } 188 fwrite(obuf,o-obuf,1,stdout); 189 return 0; 190 }
深深地明白自己的弱小