题意:一棵树,点有$0,1,2$三种颜色,支持路径修改颜色和查询点所在同色连通块的大小

lcm太可怕了,于是去问了sk,得到一个优质做法

考虑lct维护子树信息,$vs_{x,i}$为$x$的虚儿子中,以颜色为$i$的节点为根的同色连通块大小之和,$s_{x,i}$表示splay上$x$的子树$vs_{x,i}$之和,切换虚实时更新$vs$,splay上pushup时更新$s$即可

如果每时每刻都保持同一棵splay中点的颜色都相同,那么询问时只需模仿access的过程,不停往上拼接同色splay,最后得到的splay的根节点$x$的$s_{x,c_x}+siz_x$就是答案,我们把这种access称为按颜色access

现在考虑修改,先求lca,把修改拆成两个祖先后代链,假设这条祖先后代链为$y\rightarrow x$,$y$是$x$的祖先

先对$fa_y$按颜色access,再对$x\rightarrow y$无条件access,对得到的splay打标记即可

这棵splay可能会作为某个点的虚儿子,看起来要一直往上更新,实际上最多更新往上的两棵splay即可

设往上的三棵splay为$T_1,T_2,T_3$,因为$T_1$是按颜色access得到的,所以$c_{T_1}\neq c_{T_2}$

首先$T_1$显然需要更新,然后因为$T_2$需要用到$T_1$的信息,所以当$y\rightarrow x$这条链在修改前或修改后的颜色$=c_{T_1}$时,$T_1$的$s_{x,c_{T_1}}$会变化,进而影响$T_2$的$s_{x,c_{T_1}}$

幸运地,$T_3$只需要用到$T_2$的$s_{x,c_{T_2}}$信息,又因为$c_{T_1}\ne c_{T_2}$,所以从$T_3$开始往上的那些splay都无需更新

最后是无条件access所引发的一些小问题,在按颜色access时,我们可以快速而准确地更新一个节点的$vs$,但无条件access时,splay中可能含有不同颜色的点,这时不能直接用$s_{x,c_x}+siz_x$来计算$x$对父亲的$vs$的贡献

解决方法很简单:在拼接$x$和$y$之前先算出$x$对父亲的旧贡献,减掉即可,又因为一个节点原来的实儿子的splay子树中都是同颜色的点,这部分的贡献可以直接按原来的方法算

于是整道题就做完了,这个题还是挺好的==

再次orzskdtz两位人形自走dspedia

  1. #include<stdio.h>
  2. #include<algorithm>
  3. using namespace std;
  4. int n;
  5. namespace t{
  6. int h[100010],nex[100010],to[100010],M;
  7. void add(int a,int b){
  8. M++;
  9. to[M]=b;
  10. nex[M]=h[a];
  11. h[a]=M;
  12. }
  13. int fa[100010][17],dep[100010],siz[100010];
  14. void dfs(int x){
  15. dep[x]=dep[fa[x][0]]+1;
  16. siz[x]=1;
  17. for(int i=h[x];i;i=nex[i]){
  18. if(to[i]!=fa[x][0]){
  19. dfs(to[i]);
  20. siz[x]+=siz[to[i]];
  21. }
  22. }
  23. }
  24. void work(){
  25. int i,j;
  26. for(i=2;i<=n;i++){
  27. scanf("%d",fa[i]);
  28. add(fa[i][0],i);
  29. }
  30. dfs(1);
  31. for(j=1;j<17;j++){
  32. for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];
  33. }
  34. }
  35. int lca(int x,int y){
  36. int i;
  37. if(dep[x]<dep[y])swap(x,y);
  38. for(i=16;i>=0;i--){
  39. if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
  40. }
  41. if(x==y)return x;
  42. for(i=16;i>=0;i--){
  43. if(fa[x][i]!=fa[y][i]){
  44. x=fa[x][i];
  45. y=fa[y][i];
  46. }
  47. }
  48. return fa[x][0];
  49. }
  50. }
  51. namespace l{
  52. int ch[100010][2],fa[100010],r[100010],siz[100010],s[100010][3],vs[100010][3],d[100010],c[100010];
  53. #define ls ch[x][0]
  54. #define rs ch[x][1]
  55. void pushup(int x){
  56. for(int i=0;i<3;i++)s[x][i]=s[ls][i]+s[rs][i]+vs[x][i];
  57. r[x]=rs?r[rs]:x;
  58. siz[x]=siz[ls]+siz[rs]+1;
  59. }
  60. void rot(int x){
  61. int y,z,f,b;
  62. y=fa[x];
  63. z=fa[y];
  64. f=ch[y][0]==x;
  65. b=ch[x][f];
  66. fa[x]=z;
  67. fa[y]=x;
  68. if(b)fa[b]=y;
  69. ch[x][f]=y;
  70. ch[y][f^1]=b;
  71. if(ch[z][0]==y)ch[z][0]=x;
  72. if(ch[z][1]==y)ch[z][1]=x;
  73. pushup(y);
  74. pushup(x);
  75. }
  76. void set(int x,int v){
  77. d[x]=c[x]=v;
  78. }
  79. void pushdown(int x){
  80. if(~d[x]){
  81. if(ls)set(ls,d[x]);
  82. if(rs)set(rs,d[x]);
  83. d[x]=-1;
  84. }
  85. }
  86. bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
  87. void gao(int x){
  88. if(!isrt(x))gao(fa[x]);
  89. pushdown(x);
  90. }
  91. void splay(int x){
  92. gao(x);
  93. int y,z;
  94. while(!isrt(x)){
  95. y=fa[x];
  96. z=fa[y];
  97. if(!isrt(y))rot((ch[z][0]==y)^(ch[y][0]==x)?x:y);
  98. rot(x);
  99. }
  100. }
  101. void work(){
  102. int i;
  103. for(i=1;i<=n;i++){
  104. fa[i]=t::fa[i][0];
  105. r[i]=i;
  106. d[i]=-1;
  107. siz[i]=1;
  108. vs[i][0]=s[i][0]=t::siz[i]-1;
  109. }
  110. }
  111. #define v(x) (s[x][c[x]]+siz[x])
  112. void access(int x,int z){
  113. int y,t;
  114. splay(x);
  115. y=0;
  116. t=0;
  117. while(x){
  118. splay(x);
  119. if(r[x]==z)break;
  120. vs[x][c[rs]]+=v(rs);
  121. vs[x][c[y]]-=t;
  122. t=v(x);
  123. rs=y;
  124. pushup(x);
  125. y=x;
  126. x=fa[x];
  127. }
  128. }
  129. int query(int x){
  130. int y,v;
  131. splay(x);
  132. y=0;
  133. v=c[x];
  134. while(x){
  135. splay(x);
  136. if(c[x]!=v)break;
  137. vs[x][c[rs]]+=v(rs);
  138. vs[x][c[y]]-=v(y);
  139. rs=y;
  140. pushup(x);
  141. y=x;
  142. x=fa[x];
  143. }
  144. return s[y][v]+siz[y];
  145. }
  146. }
  147. void modify(int x,int y,int v){
  148. using namespace l;
  149. int z=t::fa[y][0];
  150. if(z){
  151. query(z);
  152. splay(z);
  153. if(fa[z]){
  154. splay(fa[z]);
  155. vs[fa[z]][c[z]]-=v(z);
  156. }
  157. splay(y);
  158. vs[z][c[y]]-=v(y);
  159. }
  160. access(x,z);
  161. splay(x);
  162. set(x,v);
  163. if(z){
  164. splay(y);
  165. vs[z][c[y]]+=v(y);
  166. pushup(z);
  167. if(fa[z]){
  168. vs[fa[z]][c[z]]+=v(z);
  169. pushup(fa[z]);
  170. }
  171. }
  172. }
  173. int main(){
  174. int m,i,x,y,z,k;
  175. scanf("%d%d",&n,&m);
  176. t::work();
  177. l::work();
  178. while(m--){
  179. scanf("%d",&i);
  180. if(i==1){
  181. scanf("%d%d%d",&x,&y,&z);
  182. k=t::lca(x,y);
  183. modify(x,k,z);
  184. modify(y,k,z);
  185. }else{
  186. scanf("%d",&x);
  187. printf("%d\n",l::query(x));
  188. }
  189. }
  190. }

[xsy2913]enos的更多相关文章

  1. 【xsy2913】 enos 动态dp

    题目大意:给你一棵 $n$个点 以 $1$为根 的树,每个点有$ 0,1,2 $三种颜色之一,初始时整棵树的颜色均为 $0$. $m$ 次操作, 每次操作形如: 1 x y c : 将 $x$到$y$ ...

  2. ng-table 简单实例

    今天用的AngularJs需要做个分页,于是用ng-table去实现,不过这个官网感觉有点坑,说的不够清楚. 下面实现了一个Demo实力,代码如下: <!DOCTYPE html> < ...

  3. AngularJs 动态加载模块和依赖

    最近项目比较忙额,白天要上班,晚上回来还需要做Angular知识点的ppt给同事,毕竟年底要辞职了,项目的后续开发还是需要有人接手的,所以就占用了晚上学习的时间.本来一直不打算写这些第三方插件的学习笔 ...

  4. ui-grid

    html代码: <html ng-app="myApp">       <head>         <meta charset="utf- ...

  5. [转]ng-grid

    本文转自:http://angular-ui.github.io/ui-grid/ Getting Started Steps for getting started (example on righ ...

  6. IGS_学习笔记10_IREP监控SOA Integration和日志设定(案例)

    20150506 Created By BaoXinjian

  7. CentOS7.1 使用资源搜集

    1.配置java环境 -openjdk* 测试 java -version 2.安装Tomcat8.0.35 点击题目可以参考源网页,但有些代码无法执行,更改如下(亲测可行): 一定要先安装java环 ...

  8. [转帖][超级少儿不宜]一氧化氮(NO),为什么亚洲人是最硬

    阴茎科学:一氧化氮(NO),为什么亚洲人是最硬 尼堪巴图鲁   ​关注他 2,911 人赞同了该文章   https://zhuanlan.zhihu.com/p/55941740 超级少儿不宜.. ...

  9. 物联网全景动态图谱2.0|PaaS物联网平台汇总(上篇)

    物联网智库 原创 物联网智库 整理发布 转载请注明来源和出处 ------   [导读]   ------ 毫无疑问,2018年物联网对行业的深度变革才刚刚开启. 物联网产业链企业的质与量将进入全面爆 ...

随机推荐

  1. js面向对象编程思想

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  2. UNIX网络编程 第8章 基本UDP套接字编程

    UDP是无连接的,不需要accept,TCP通过accept API来接受连接,并且将连接客户端的信息写入到accept将返回的新socket中,该新socket中有服务端和客户端的IP地址和端口,因 ...

  3. http、https 等 常用默认端口号

    ⑴. HTTP协议代理服务器常用端口号:80/8080/3128/8081/9080⑵. SOCKS代理协议服务器常用端口号:1080⑶. FTP(文件传输)协议代理服务器常用端口号:21⑷. Tel ...

  4. 【黑客免杀攻防】读书笔记15 - 源码免杀、C++壳的编写

    1.源码免杀 1.1 定位产生特征的源码 定位文件特征 1.根据MyCCL的特征码定位工具,定位出有特征的地址 2.根据VS的反汇编窗口,输入有特征的地址得到特征地址与源码的关系 3.插入Messag ...

  5. 关于app的cpu占用率想到的几个问题

    1.top 命令获取的cpu是手机瞬间的cpu 2.dumpsys获取的是一段时间cpu的平均值?那么这段时间是指哪段,从哪开始到什么时候结束? 3.如果想测试app某操作下的cpu占用情况时候.应该 ...

  6. C#基础学习之FileStream

    FileStream和File的区别  后者比前者给内存带来压力大. FileStream可以操作字节也就是可以保存任何类型的文件. 1.FileStream读文件操作 //OpenOrCreate: ...

  7. HDU 2825 Wireless Password

    题目链接:HDU-2825 题意:给出m个单词,要构造出满足包含其中大于等于k个单词的字符串,字符只包括小写字母,问长度为n的这样的串有多少个. 思路:令dp[i][j][k]表示当前已经构造了i个字 ...

  8. UrlRouteModule

    一.请求流程 当一个请求发往ASP.net MVC站点时的情景,IIS收到请求并将请求转到ASP.net,然后根据URL,或者更确切来说:被请求文件的扩展名.在IIS7 integrated模式下(默 ...

  9. Code Conventions for the JavaScript Programming Language

    This is a set of coding conventions and rules for use in JavaScript programming. It is inspired by t ...

  10. hihoCoder #1185 : 连通性·三(强联通分量+拓扑排序)

    #1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...