BZOJ4817: [Sdoi2017]树点涂色(LCT)

Description

Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
1 x:
把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
2 x y:
求x到y的路径的权值。
3 x
在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
Bob一共会进行m次操作

Input

第一行两个数n,m。
接下来n-1行,每行两个数a,b,表示a与b之间有一条边。
接下来m行,表示操作,格式见题目描述
1<=n,m<=100000

Output

每当出现2,3操作,输出一行。
如果是2操作,输出一个数表示路径的权值
如果是3操作,输出一个数表示权值的最大值 

Sample Input

5 6
1 2
2 3
3 4
3 5
2 4 5
3 3
1 4
2 4 5
1 5
2 4 5

Sample Output

3
4
2
2

解题思路:

LCT好题access构造。

将第一个操作视为access操作并更新答案。

那么开始时视为没有轻重链。

access过程中若发生轻重链转化时将子树答案都加1,并撤销上一节点操作。

这样就可以在每一个节点上维护到根的权值和。

第三问直接解决。

第二问呢,发现合并两条链的代价就是两个链单独的代价-2*lca代价+1(因为lca节点需要考虑)

子树修改普通Dfs就好了。

代码:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6 #define ls ch[0]
  7 #define rs ch[1]
  8 typedef long long lnt;
  9 const int N=300000;
 10 struct seg_trnt{
 11     int lzt;
 12     int maxval;
 13 }ter[N<<2];
 14 struct spl_trnt{
 15     int ch[2];
 16     int fa;
 17     int lzt;
 18     bool anc;
 19 }tr[N];
 20 struct pnt{
 21     int hd;
 22     int dp;
 23     int ind;
 24     int oud;
 25     int fa[20];
 26 }p[N];
 27 struct ent{
 28     int twd;
 29     int lst;
 30 }e[N<<1];
 31 int n,m;
 32 int cnt;
 33 int dfn;
 34 bool sta=true;
 35 int pos[N];
 36 void pushup(int spc)
 37 {
 38     ter[spc].maxval=std::max(ter[spc<<1].maxval,ter[spc<<1|1].maxval);
 39     return ;
 40 }
 41 void ppushdown(int spc)
 42 {
 43     if(ter[spc].lzt)
 44     {
 45         ter[spc<<1].maxval+=ter[spc].lzt;
 46         ter[spc<<1|1].maxval+=ter[spc].lzt;
 47         ter[spc<<1].lzt+=ter[spc].lzt;
 48         ter[spc<<1|1].lzt+=ter[spc].lzt;
 49         ter[spc].lzt=0;
 50     }
 51     return ;
 52 }
 53 void update(int l,int r,int ll,int rr,int spc,int v)
 54 {
 55     if(ll>r||l>rr)
 56         return ;
 57     if(ll<=l&&r<=rr)
 58     {
 59         ter[spc].maxval+=v;
 60         ter[spc].lzt+=v;
 61         return ;
 62     }
 63     ppushdown(spc);
 64     int mid=(l+r)>>1;
 65     update(l,mid,ll,rr,spc<<1,v);
 66     update(mid+1,r,ll,rr,spc<<1|1,v);
 67     pushup(spc);
 68     return ;
 69 }
 70 int maxq(int l,int r,int ll,int rr,int spc)
 71 {
 72     if(ll>r||l>rr)
 73         return -0x3f3f3f3f;
 74     if(ll<=l&&r<=rr)
 75         return ter[spc].maxval;
 76     int mid=(l+r)>>1;
 77     ppushdown(spc);
 78     return std::max(maxq(l,mid,ll,rr,spc<<1),maxq(mid+1,r,ll,rr,spc<<1|1));
 79 }
 80 int query(int l,int r,int pos,int spc)
 81 {
 82     if(l==r)
 83         return ter[spc].maxval;
 84     ppushdown(spc);
 85     int mid=(l+r)>>1;
 86     if(pos<=mid)
 87         return query(l,mid,pos,spc<<1);
 88     return query(mid+1,r,pos,spc<<1|1);
 89 }
 90 void build(int l,int r,int spc)
 91 {
 92     if(l==r)
 93     {
 94         ter[spc].maxval=p[pos[l]].dp;
 95         return ;
 96     }
 97     int mid=(l+r)>>1;
 98     build(l,mid,spc<<1);
 99     build(mid+1,r,spc<<1|1);
100     pushup(spc);
101     return ;
102 }
103 void ade(int f,int t)
104 {
105     cnt++;
106     e[cnt].twd=t;
107     e[cnt].lst=p[f].hd;
108     p[f].hd=cnt;
109     return ;
110 }
111 void dfs(int x,int f)
112 {
113     p[x].dp=p[f].dp+1;
114     p[x].fa[0]=f;
115     pos[++dfn]=x;
116     p[x].ind=dfn;
117     for(int i=1;i<=19;i++)
118         p[x].fa[i]=p[p[x].fa[i-1]].fa[i-1];
119     for(int i=p[x].hd;i;i=e[i].lst)
120     {
121         int to=e[i].twd;
122         if(to==f)
123             continue;
124         tr[to].fa=x;
125         dfs(to,x);
126     }
127     p[x].oud=dfn;
128     return ;
129 }
130 int Lca(int x,int y)
131 {
132     if(p[x].dp<p[y].dp)
133         std::swap(x,y);
134     for(int i=19;i>=0;i--)
135     {
136         if(p[p[x].fa[i]].dp>=p[y].dp)
137             x=p[x].fa[i];
138     }
139     if(x==y)
140         return x;
141     for(int i=19;i>=0;i--)
142     {
143         if(p[x].fa[i]!=p[y].fa[i])
144             x=p[x].fa[i],y=p[y].fa[i];
145     }
146     return p[x].fa[0];
147 }
148 bool whc(int spc)
149 {
150     return tr[tr[spc].fa].rs==spc;
151 }
152 void trr(int spc)
153 {
154     if(!spc)
155         return ;
156     std::swap(lll,rrr);
157     tr[spc].lzt^=1;
158     return ;
159 }
160 void pushdown(int spc)
161 {
162     if(tr[spc].lzt)
163     {
164         tr[spc].lzt=0;
165         trr(lll);
166         trr(rrr);
167     }
168     return ;
169 }
170 void recal(int spc)
171 {
172     if(!tr[spc].anc)
173         recal(tr[spc].fa);
174     pushdown(spc);
175     return ;
176 }
177 void rotate(int spc)
178 {
179     int f=tr[spc].fa;
180     bool k=whc(spc);
181     tr[f].ch[k]=tr[spc].ch[!k];
182     tr[spc].ch[!k]=f;
183     if(tr[f].anc)
184     {
185         tr[f].anc=0;
186         tr[spc].anc=1;
187     }else
188         tr[tr[f].fa].ch[whc(f)]=spc;
189     tr[spc].fa=tr[f].fa;
190     tr[f].fa=spc;
191     tr[tr[f].ch[k]].fa=f;
192     return ;
193 }
194 void splay(int spc)
195 {
196     recal(spc);
197     while(!tr[spc].anc)
198     {
199         int f=tr[spc].fa;
200         if(tr[f].anc)
201         {
202             rotate(spc);
203             return ;
204         }
205         if(whc(spc)^whc(f))
206             rotate(spc);
207         else
208             rotate(f);
209         rotate(spc);
210     }
211     return ;
212 }
213 int leftpos(int spc)
214 {
215     pushdown(spc);
216     while(lll)
217     {
218         spc=lll;
219         pushdown(spc);
220     }
221     return spc;
222 }
223 void access(int spc)
224 {
225     int lst=0,x;
226     while(spc)
227     {
228         splay(spc);
229         tr[lst].anc=0;
230         tr[rrr].anc=1;
231         x=leftpos(rrr);
232         if(x&&!sta)
233             update(1,n,p[x].ind,p[x].oud,1,1);
234         x=leftpos(lst);
235         if(x&&!sta)
236             update(1,n,p[x].ind,p[x].oud,1,-1);
237         rrr=lst;
238         lst=spc;
239         spc=tr[spc].fa;
240     }
241     return ;
242 }
243 void Mtr(int spc)
244 {
245     access(spc);
246     splay(spc);
247     trr(spc);
248     return ;
249 }
250 void split(int x,int y)
251 {
252     Mtr(x);
253     access(y);
254     splay(y);
255     return ;
256 }
257 void link(int x,int y)
258 {
259     split(x,y);
260     tr[x].fa=y;
261     return ;
262 }
263 int main()
264 {
265     scanf("%d%d",&n,&m);
266     for(int i=1;i<=n;i++)
267     {
268         tr[i].anc=true;
269     }
270     for(int i=1;i<n;i++)
271     {
272         int a,b;
273         scanf("%d%d",&a,&b);
274         ade(a,b);
275         ade(b,a);
276     }
277     dfs(1,1);
278     build(1,n,1);
279     sta=false;
280     while(m--)
281     {
282         int cmd;
283         scanf("%d",&cmd);
284         if(cmd==1)
285         {
286             int x;
287             scanf("%d",&x);
288             Mtr(1);
289             access(x);
290         }else if(cmd==2)
291         {
292             int ans=1;
293             int x,y;
294             scanf("%d%d",&x,&y);
295             int z=Lca(x,y);
296             ans+=query(1,n,p[x].ind,1);
297             ans+=query(1,n,p[y].ind,1);
298             ans-=query(1,n,p[z].ind,1)<<1;
299             printf("%d\n",ans);
300         }else{
301             int x;
302             scanf("%d",&x);
303             printf("%d\n",maxq(1,n,p[x].ind,p[x].oud,1));
304         }
305     }
306     return 0;
307 }

 

posted @ 2018-12-13 21:09  Unstoppable728  阅读(307)  评论(0编辑  收藏  举报