1. 程式人生 > >bzoj3159決戰 碼農題 樹剖套splay

bzoj3159決戰 碼農題 樹剖套splay

== 但是 bzoj3 fin wap names 碼農 find turn

最近沈迷碼農題無法自拔

首先有一個暴力的想法:對於每個重鏈維護一個splay,需要翻轉的連起來,翻轉,接回去

然後發現這樣沒問題。。。

一條鏈只能跨log個重鏈,也就只有log個splay的子樹參與重排,所以一次翻轉只要log^2的時間

需要維護的東西有點多

頭一次在splay上維護這麽多亂七八糟的東西,寫錯了好幾遍

感覺學到不少debug技巧,也糾正了之前splay寫法的一個小漏洞

話說極限數據好像和miaom拍不過啊。。。但是我們都A了啊

好煩啊不知道誰出鍋了

  1 #include <bits/stdc++.h>
  2 #define num(x) (dep[x]-dep[top[x]]+1)
  3
#define ans tr[split(num(x),num(y))] 4 #define rt root[RT] 5 #define RT1 root[n+1] 6 #define NO 800000 7 #define N 800000 8 #define INF 2000000000 9 #define ll long long 10 using namespace std; 11 struct trnode 12 { 13 int size,min,max;ll sum;int plus,num; 14 bool rev; 15 trnode() 16 {
17 size=1;min=max=sum=plus=rev=num=0; 18 } 19 } tr[NO]; 20 int n,m,R,p,q,RT,x,y,z,RET,E,NODE,sttop,inv_x,inv_y;ll ret; 21 int c[NO][2],fa[NO];bool die[N]; 22 int root[N],Fa[N],size[N],fir[N],top[N],dep[N],st[N],sz[N],lin[N]; 23 int nex[2*N],to[2*N]; 24 char cmd[10]; 25 void up(int x)
26 { 27 if(!x) 28 { 29 tr[0]=trnode();tr[0].size=0; 30 return; 31 } 32 tr[x].size=tr[c[x][0]].size+tr[c[x][1]].size+1; 33 tr[x].sum=tr[c[x][0]].sum+tr[c[x][1]].sum+(ll)tr[x].plus*tr[x].size+tr[x].num; 34 tr[x].max=max(tr[c[x][0]].max,tr[c[x][1]].max)+tr[x].plus; 35 tr[x].max=max(tr[x].max,tr[x].num+tr[x].plus); 36 tr[x].min=tr[x].num; 37 if(c[x][0]!=0) 38 tr[x].min=min(tr[x].min,tr[c[x][0]].min); 39 if(c[x][1]!=0) 40 tr[x].min=min(tr[x].min,tr[c[x][1]].min); 41 tr[x].min+=tr[x].plus; 42 } 43 void down(int x) 44 { 45 if(tr[x].rev) 46 swap(c[x][0],c[x][1]),tr[c[x][0]].rev^=1,tr[c[x][1]].rev^=1,tr[x].rev=0; 47 if(tr[x].plus) 48 tr[c[x][0]].plus+=tr[x].plus,tr[c[x][1]].plus+=tr[x].plus, 49 tr[x].num+=tr[x].plus,tr[x].plus=0,up(c[x][0]),up(c[x][1]); 50 } 51 void rot(int x) 52 { 53 down(fa[x]);down(x); 54 int y=fa[x],k=c[y][1]==x; 55 if(fa[y]) c[fa[y]][c[fa[y]][1]==y]=x; 56 else rt=x; 57 fa[x]=fa[y];fa[y]=x; 58 c[y][k]=c[x][!k]; 59 if(c[x][!k]) 60 fa[c[x][!k]]=y; 61 c[x][!k]=y; 62 up(y);up(x); 63 } 64 void splay(int x,int z) 65 { 66 for(int y;(y=fa[x])!=z;rot(x)) 67 if(fa[y]!=z) 68 rot(c[fa[y]][1]==y^c[y][1]==x?x:y); 69 } 70 int Find(int x) 71 { 72 if(x==0) return -1; 73 if(x>tr[rt].size) return -1; 74 int now=rt; 75 while(down(now),tr[c[now][0]].size+1!=x) 76 if(x<=tr[c[now][0]].size) 77 now=c[now][0]; 78 else 79 x-=tr[c[now][0]].size+1,now=c[now][1]; 80 return now; 81 } 82 int split(int x,int y) 83 { 84 if(x==1 && y==tr[rt].size) 85 return rt; 86 if(x==1) 87 { splay(Find(y+1),0);return c[rt][0];} 88 if(y==tr[rt].size) 89 { splay(Find(x-1),0);return c[rt][1];} 90 splay(Find(x-1),0); 91 splay(Find(y+1),rt); 92 return c[c[rt][1]][0]; 93 } 94 void upd(int x) 95 { 96 int len=0; 97 while(x) 98 lin[++len]=x,x=fa[x]; 99 for(int i=len;i;i--) 100 down(lin[i]); 101 for(int i=1;i<=len;i++) 102 up(lin[i]); 103 } 104 int Split(int x,int y) 105 { 106 int p=split(x,y),q=fa[p]; 107 upd(p); 108 fa[p]=0;c[q][c[q][1]==p]=0; 109 upd(q); 110 splay(q,0); 111 return p; 112 } 113 void work(int x,int y) 114 { 115 RT=top[x];int tem; 116 if(cmd[2]==c) 117 tr[tem=split(num(x),num(y))].plus+=z,upd(tem);//? 118 if(cmd[0]==S) 119 ret+=ans.sum; 120 if(cmd[1]==a) ret=max(ret,(ll)ans.max); 121 if(cmd[1]==i) RET=min(RET,ans.min); 122 if(cmd[2]==v) 123 { 124 int tem=Split(num(x),num(y)); 125 if(tem==rt) die[RT]=1; 126 RT=n+1; 127 if(!rt) rt=tem; 128 else 129 { 130 splay(Find(1),0); 131 c[rt][0]=tem;fa[tem]=rt; 132 splay(tem,0); 133 } 134 } 135 } 136 void add(int p,int q) 137 { 138 to[++E]=q;nex[E]=fir[p];fir[p]=E; 139 } 140 int build(int now,int fat) 141 { 142 size[now]=1;Fa[now]=fat;dep[now]=dep[fat]+1; 143 for(int i=fir[now];i;i=nex[i]) 144 if(to[i]!=fat) 145 size[now]+=build(to[i],now); 146 return size[now]; 147 } 148 void ins() 149 { 150 int now=rt; 151 while(c[now][1]) now=c[now][1]; 152 c[now][1]=++NODE;fa[NODE]=now; 153 tr[NODE]=trnode(); 154 splay(NODE,0); 155 } 156 void pou(int now,int Top) 157 { 158 top[now]=Top; 159 if(Top==now) 160 tr[++NODE]=trnode(),root[now]=NODE; 161 else 162 RT=Top,ins(); 163 int id=0; 164 for(int i=fir[now];i;i=nex[i]) 165 if(to[i]!=Fa[now]) 166 if(size[to[i]]>size[id]) 167 id=to[i]; 168 if(id) pou(id,Top); 169 for(int i=fir[now];i;i=nex[i]) 170 if(to[i]!=Fa[now] && to[i]!=id) 171 pou(to[i],to[i]); 172 } 173 int main() 174 { 175 scanf("%d%d%d",&n,&m,&R); 176 for(int i=1;i<n;i++) 177 scanf("%d%d",&p,&q), 178 add(p,q),add(q,p); 179 tr[0].size=0; 180 build(R,0); 181 pou(R,R); 182 for(int i=1;i<=m;i++) 183 { 184 if(i==4) 185 int e=1; 186 scanf("%s%d%d",cmd,&x,&y); 187 if(cmd[2]==c) scanf("%d",&z); 188 ret=0;RET=INF;sttop=0; 189 while(top[x]!=top[y]) 190 { 191 if(dep[top[x]]<dep[top[y]]) swap(x,y); 192 work(top[x],x); 193 st[++sttop]=top[x];sz[sttop]=num(x); 194 x=Fa[top[x]]; 195 } 196 if(dep[x]>dep[y]) 197 swap(x,y); 198 if(cmd[2]==v) 199 { 200 RT=top[x]; 201 inv_x=Find(num(x)-1);inv_y=Find(num(y)+1); 202 } 203 work(x,y); 204 if(cmd[0]==S || cmd[1]==a) printf("%lld\n",ret); 205 if(cmd[1]==i) printf("%d\n",RET); 206 if(cmd[2]==v) 207 { 208 RT=n+1; 209 tr[rt].rev^=1; 210 int tem=Split(1,num(y)-num(x)+1); 211 RT=top[x]; 212 if(inv_x==-1 && inv_y==-1) 213 rt=tem,die[RT]=0; 214 else 215 if(inv_x==-1) 216 { 217 splay(inv_y,0); 218 c[rt][0]=tem;fa[tem]=rt; 219 splay(tem,0); 220 } 221 else 222 if(inv_y==-1) 223 splay(inv_x,0),c[rt][1]=tem,fa[tem]=rt,splay(tem,0); 224 else 225 splay(inv_x,0),splay(inv_y,rt),c[c[rt][1]][0]=tem,fa[tem]=c[rt][1],splay(tem,0); 226 for(int i=sttop;i;i--) 227 { 228 RT=n+1; 229 int tem=Split(1,sz[i]); 230 RT=st[i]; 231 if(die[RT]) die[RT]=0,rt=tem; 232 else 233 { 234 splay(Find(1),0); 235 c[rt][0]=tem;fa[tem]=rt;splay(tem,0); 236 } 237 } 238 } 239 root[n+1]=0;die[n+1]=0; 240 } 241 return 0; 242 }

bzoj3159決戰 碼農題 樹剖套splay