【SPOJ】QTREE7(Link-Cut Tree)

题面

洛谷

Vjudge

题解

QTREE6的本质是一样的:维护同色联通块

那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\)

每次只修改和它父亲的连边。

考虑如何维护最大值

因为每次\(access\)会删去一个数,所以我们肯定不能够只维护最大值。

因此,对于每一个节点,额外维护一个\(multiset\)(当然,可删堆,\(map\)之类的也行)

每次用\(multiset\)维护虚子树的最值,拿过去更新即可。

最后的答案和QTREE6是一样的,

找到这个联通块的最浅父亲,维护一下子树最值就行啦。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<set>
  8. #include<map>
  9. #include<vector>
  10. #include<queue>
  11. using namespace std;
  12. #define ll long long
  13. #define RG register
  14. #define MAX 111111
  15. #define ls (t[x].ch[0])
  16. #define rs (t[x].ch[1])
  17. inline int read()
  18. {
  19. RG int x=0,t=1;RG char ch=getchar();
  20. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  21. if(ch=='-')t=-1,ch=getchar();
  22. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  23. return x*t;
  24. }
  25. int W[MAX];
  26. struct Link_Cut_Tree
  27. {
  28. struct Node
  29. {
  30. int ch[2],ff;
  31. int mx;
  32. multiset<int> S;
  33. }t[MAX];
  34. bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
  35. void pushup(int x)
  36. {
  37. t[x].mx=max(max(t[ls].mx,t[rs].mx),W[x]);
  38. if(!t[x].S.empty())t[x].mx=max(t[x].mx,*t[x].S.rbegin());
  39. }
  40. void rotate(int x)
  41. {
  42. int y=t[x].ff,z=t[y].ff;
  43. int k=t[y].ch[1]==x;
  44. if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
  45. t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
  46. t[x].ch[k^1]=y;t[y].ff=x;
  47. pushup(y);pushup(x);
  48. }
  49. void Splay(int x)
  50. {
  51. while(!isroot(x))
  52. {
  53. int y=t[x].ff,z=t[y].ff;
  54. if(!isroot(y))
  55. (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
  56. rotate(x);
  57. }
  58. pushup(x);
  59. }
  60. void access(int x)
  61. {
  62. for(int y=0;x;y=x,x=t[x].ff)
  63. {
  64. Splay(x);
  65. if(rs)t[x].S.insert(t[rs].mx);
  66. rs=y;
  67. if(rs)t[x].S.erase(t[rs].mx);
  68. pushup(x);
  69. }
  70. }
  71. int findroot(int x){access(x);Splay(x);while(ls)x=ls;Splay(x);return x;}
  72. void link(int x,int y){if(!y)return;access(y);Splay(y);Splay(x);t[x].ff=y;t[y].ch[1]=x;pushup(y);}
  73. void cut(int x,int y){if(!y)return;access(x);Splay(x);ls=t[ls].ff=0;pushup(x);}
  74. }LCT[2];
  75. struct Line{int v,next;}e[MAX<<1];
  76. int h[MAX],cnt=1,fa[MAX],n,Q,c[MAX];
  77. inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
  78. void dfs(int u,int ff)
  79. {
  80. for(int i=h[u];i;i=e[i].next)
  81. {
  82. int v=e[i].v;if(v==ff)continue;
  83. fa[v]=u;LCT[c[v]].link(v,u);dfs(v,u);
  84. }
  85. }
  86. int main()
  87. {
  88. n=read();
  89. for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
  90. for(int i=1;i<=n;++i)c[i]=read();
  91. for(int i=1;i<=n;++i)W[i]=read();
  92. LCT[0].t[0].mx=LCT[1].t[0].mx=-2e9;
  93. dfs(1,0);Q=read();
  94. while(Q--)
  95. {
  96. int opt=read(),u=read();
  97. if(opt==0)
  98. {
  99. int ff=LCT[c[u]].findroot(u);
  100. if(c[u]==c[ff])printf("%d\n",LCT[c[u]].t[ff].mx);
  101. else printf("%d\n",LCT[c[u]].t[LCT[c[u]].t[ff].ch[1]].mx);
  102. }
  103. else if(opt==1)LCT[c[u]].cut(u,fa[u]),c[u]^=1,LCT[c[u]].link(u,fa[u]);
  104. else
  105. {
  106. LCT[c[u]].access(u);LCT[c[u]].Splay(u);
  107. W[u]=read();LCT[c[u]].pushup(u);
  108. }
  109. }
  110. return 0;
  111. }

【SPOJ】QTREE7(Link-Cut Tree)的更多相关文章

  1. 【SPOJ】Highways(矩阵树定理)

    [SPOJ]Highways(矩阵树定理) 题面 Vjudge 洛谷 题解 矩阵树定理模板题 无向图的矩阵树定理: 对于一条边\((u,v)\),给邻接矩阵上\(G[u][v],G[v][u]\)加一 ...

  2. LCT(Link Cut Tree)总结

    概念.性质简述 首先介绍一下链剖分的概念链剖分,是指一类对树的边进行轻重划分的操作,这样做的目的是为了减少某些链上的修改.查询等操作的复杂度.目前总共有三类:重链剖分,实链剖分和并不常见的长链剖分. ...

  3. 【SPOJ】QTREE6(Link-Cut-Tree)

    [SPOJ]QTREE6(Link-Cut-Tree) 题面 Vjudge 题解 很神奇的一道题目 我们发现点有黑白两种,又是动态加边/删边 不难想到\(LCT\) 最爆力的做法,显然是每次修改单点颜 ...

  4. 【SPOJ】Substrings(后缀自动机)

    [SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...

  5. 【CF487E】Tourists(圆方树)

    [CF487E]Tourists(圆方树) 题面 UOJ 题解 首先我们不考虑修改,再来想想这道题目. 我们既然要求的是最小值,那么,在经过一个点双的时候,走的一定是具有较小权值的那一侧. 所以说,我 ...

  6. 【CF17E】Palisection(回文树)

    [CF17E]Palisection(回文树) 题面 洛谷 题解 题意: 求有重叠部分的回文子串对的数量 所谓正难则反 求出所有不重叠的即可 求出以一个位置结束的回文串的数量 和以一个位置为开始的回文 ...

  7. 【BZOJ3160】万径人踪灭(FFT,Manacher)

    [BZOJ3160]万径人踪灭(FFT,Manacher) 题面 BZOJ 题解 很容易想到就是满足条件的子序列个数减去回文子串的个数吧... 至于满足条件的子序列 我们可以依次枚举对称轴 如果知道关 ...

  8. 【BZOJ3944】Sum(杜教筛)

    [BZOJ3944]Sum(杜教筛) 题面 求\[\sum_{i=1}^n\mu(i)和\sum_{i=1}^n\phi(i)\] 范围:\(n<2^{31}\) 令\[S(n)=\sum_{i ...

  9. 【BZOJ3730】震波(动态点分治)

    [BZOJ3730]震波(动态点分治) 题面 BZOJ 题意 给定一棵树, 每次询问到一个点的距离\(<=K\)的点的权值之和 动态修改权值, 强制在线 题解 正常的\(DP\)??? 很简单呀 ...

随机推荐

  1. Java SE教程

    第0讲 开山篇 读前介绍:本文中如下文本格式是超链接,可以点击跳转 >>超链接<< 我的学习目标:基础要坚如磐石   代码要十份规范   笔记要认真详实 一.java内容介绍 ...

  2. 使用GUI工具高效构建你自己的Nuget包

    写这篇文章的原因是我在学习构建nuget包的时候,发现了一个官方推荐的GUI工具,而官方的工具介绍文章已经过时,一些地方和现在最新版本的工具有些差异,所以特意利用假期最后一个下午写下来,希望能帮助更多 ...

  3. qt cout输出中文乱码解决记录

    工具 -> 选项-> 文本编辑器-> 行为 -> 文件编码->默认编码改为System 乱码原因: 默认用utf-8编码,控制台默认gbk编码,编码不一致导致的乱码

  4. PHP自定义生成二维码跳转地址

      比较简单的一款PHP自定义生成二维码跳转地址,手机端微信扫码,自动跳转到定义好的链接.支持自定义生成二维码尺寸.间距等.    鼠标悬浮显示二维码弹出层,离开后消失.js实现,代码如下: $(fu ...

  5. ArrayList 源码分析 -- 扩容问题及序列化问题

    目录 一.前言二.ArrayList 的继承与实现关系    2.1 ArrayList.java    2.2 抽象类AbstractList.java    2.3 接口List.java     ...

  6. mysql数据导到本地

    需求: 把mysql查询结果导出到txt(其他格式亦可),放在本地,供下一步使用 首先网上查了下,select * from driver into outfile 'a.txt'; 前面是你的sql ...

  7. Nginx快速入门

    本文主要介绍nginx的基本配置和操作,并介绍了一些可以完成的简单任务. 假设您已经学习过并已经安装好了nginx服务器. 如果没有,请参阅安装nginx页面(http://www.yiibai.co ...

  8. spark的数据结构 RDD——DataFrame——DataSet区别

    转载自:http://blog.csdn.net/wo334499/article/details/51689549 RDD 优点: 编译时类型安全 编译时就能检查出类型错误 面向对象的编程风格 直接 ...

  9. 王者荣耀交流协会第一次scrum会议

    照片: 拍照的人是我(高远博),没有出镜.开会时间是17:00到17:37. 昨天的成绩: (1)优化了折线图界面 今天的计划: (1)小组成员汇报昨日成果. (2)小组成员继续推进任务. 遇到的困难 ...

  10. IT小小鸟读后感言

    有感 读了我是一只IT小小鸟之后, 我发现上大学得靠自己自学,确定自己的目标和方向,多去参与实验和自己多锻炼编写程序.我现在大一,还有很多时间来让自己变得更好,虽然要补考两门课程,但是还是不要失去信心 ...