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=;
  10. struct seg_trnt{
  11. int lzt;
  12. int maxval;
  13. }ter[N<<];
  14. struct spl_trnt{
  15. int ch[];
  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[];
  26. }p[N];
  27. struct ent{
  28. int twd;
  29. int lst;
  30. }e[N<<];
  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<<].maxval,ter[spc<<|].maxval);
  39. return ;
  40. }
  41. void ppushdown(int spc)
  42. {
  43. if(ter[spc].lzt)
  44. {
  45. ter[spc<<].maxval+=ter[spc].lzt;
  46. ter[spc<<|].maxval+=ter[spc].lzt;
  47. ter[spc<<].lzt+=ter[spc].lzt;
  48. ter[spc<<|].lzt+=ter[spc].lzt;
  49. ter[spc].lzt=;
  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)>>;
  65. update(l,mid,ll,rr,spc<<,v);
  66. update(mid+,r,ll,rr,spc<<|,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)>>;
  77. ppushdown(spc);
  78. return std::max(maxq(l,mid,ll,rr,spc<<),maxq(mid+,r,ll,rr,spc<<|));
  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)>>;
  86. if(pos<=mid)
  87. return query(l,mid,pos,spc<<);
  88. return query(mid+,r,pos,spc<<|);
  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)>>;
  98. build(l,mid,spc<<);
  99. build(mid+,r,spc<<|);
  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+;
  114. p[x].fa[]=f;
  115. pos[++dfn]=x;
  116. p[x].ind=dfn;
  117. for(int i=;i<=;i++)
  118. p[x].fa[i]=p[p[x].fa[i-]].fa[i-];
  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=;i>=;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=;i>=;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[];
  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^=;
  158. return ;
  159. }
  160. void pushdown(int spc)
  161. {
  162. if(tr[spc].lzt)
  163. {
  164. tr[spc].lzt=;
  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=;
  186. tr[spc].anc=;
  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=,x;
  226. while(spc)
  227. {
  228. splay(spc);
  229. tr[lst].anc=;
  230. tr[rrr].anc=;
  231. x=leftpos(rrr);
  232. if(x&&!sta)
  233. update(,n,p[x].ind,p[x].oud,,);
  234. x=leftpos(lst);
  235. if(x&&!sta)
  236. update(,n,p[x].ind,p[x].oud,,-);
  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=;i<=n;i++)
  267. {
  268. tr[i].anc=true;
  269. }
  270. for(int i=;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(,);
  278. build(,n,);
  279. sta=false;
  280. while(m--)
  281. {
  282. int cmd;
  283. scanf("%d",&cmd);
  284. if(cmd==)
  285. {
  286. int x;
  287. scanf("%d",&x);
  288. Mtr();
  289. access(x);
  290. }else if(cmd==)
  291. {
  292. int ans=;
  293. int x,y;
  294. scanf("%d%d",&x,&y);
  295. int z=Lca(x,y);
  296. ans+=query(,n,p[x].ind,);
  297. ans+=query(,n,p[y].ind,);
  298. ans-=query(,n,p[z].ind,)<<;
  299. printf("%d\n",ans);
  300. }else{
  301. int x;
  302. scanf("%d",&x);
  303. printf("%d\n",maxq(,n,p[x].ind,p[x].oud,));
  304. }
  305. }
  306. return ;
  307. }

BZOJ4817: [Sdoi2017]树点涂色(LCT)的更多相关文章

  1. [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status ...

  2. BZOJ4817[Sdoi2017]树点涂色——LCT+线段树

    题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...

  3. 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树

    [BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...

  4. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 629  Solved: 371[Submit][Status ...

  5. [Sdoi2017]树点涂色 [lct 线段树]

    [Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...

  6. BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)

    题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...

  7. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  8. BZOJ4817 [Sdoi2017]树点涂色 【LCT + 线段树】

    题目 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进行这 ...

  9. 【bzoj4817】[Sdoi2017]树点涂色 LCT+LCA+线段树

    题目描述 给出一棵n个点,以1为根的有根树,每个点初始染有互不相同的颜色.定义一条路径的权值为路径上的颜色种类数.现有m次操作,每次操作为以下三种之一: 1 x: 把点x到根节点的路径上所有的点染上一 ...

随机推荐

  1. leetcode第一刷_Text Justification

    这个题的接受率好低,搞得我一直不敢做.后来认真的看了一下题目,不是非常难嘛.字符串的题目ac率就是低,除了难,还由于它的測试用例太多. 思路不难,主要是由于特殊情况太多.纯模拟,我把全部的情况罗列一下 ...

  2. JsonRequestBehavior.AllowGet 方便浏览器调试

    [HttpGet] public ActionResult getCoversationList(int CustomerId) { // 获取用户相关的聊天数据,包括个人,群,系统(可以单独获取) ...

  3. FZU--2188--过河(bfs暴力条件判断)

    过河I Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status De ...

  4. 23.IDEA 运行junit单元测试方法

    转自:https://blog.csdn.net/weixin_42231507/article/details/80714716 配置Run,增加Junit 最终配置如下:

  5. 对Jscript操作注册表接口的一点不解

    作者:朱金灿 来源:http://blog.csdn.net/clever101 要操作注册表需要通过ActiveX控件调用WScript.shell对象,通过该对象的一些方法来操作.Wshshell ...

  6. 定时器函数SetTimer

    原文链接:http://www.cnblogs.com/zhangpengshou/archive/2009/04/05/1429770.html 一.SetTimer表示的是定义个定时器.根据定义指 ...

  7. 如何利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例

    前几天给大家分享了利用Python网络爬虫抓取微信朋友圈的动态(上)和利用Python网络爬虫爬取微信朋友圈动态——附代码(下),并且对抓取到的数据进行了Python词云和wordart可视化,感兴趣 ...

  8. nodejs操作文件和数据流

    前言 node中有一组流api,它们可以像处理网络流一样处理文件.流api用起来非常方便,本节学习介绍文件处理基础和流的概念. 目录 处理文件路径 fs核心模块简介 操作流 慢客户端问题 1. 处理文 ...

  9. h5播放音乐

    h5音频播放,里面參数能够查看http://www.w3school.com.cn/html5/html_5_audio.asp <audio controls="controls&q ...

  10. FocusChange-焦点变化监听事件

    想要监听一个控件的焦点变化情况,发现了一个 view.setOnFocusChangeListener(new OnFocusChangeListener() { ...... } 现在写一个小dem ...