bzoj3159决战 码农题 树剖套splay

最近沉迷码农题无法自拔

首先有一个暴力的想法:对于每个重链维护一个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 } 

 

转载于:https://www.cnblogs.com/wanglichao/p/7298861.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值