Description

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),

如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

Sample Input

6 5

2 2 1 2 1 1

1 2

1 3

2 4

2 5

2 6

Q 3 5

C 2 1 1

Q 3 5

C 5 1 2

Q 3 5

Sample Output

3

1

2

HINT

数N<=105,操作数M<=105,所有的颜色C为整数且在[0, 10^9]之间。

Solution

这题有很多做法,树剖,LCT

因为现在正在练LCT,所以就用LCT写了

一条链上,维护四个东西,col(结点本身颜色),lco(结点包括其Splay子树代表的一段颜色的最左边颜色),rco(这个就是最右边的),sum(结点包括其Splay子树代表的一段的答案)

因为LCT的Splay保证了中序遍历按深度递增,所以一个结点包括其子树后包含的位置一定是连续的一段,所以可以这样维护

然后对于pushup

首先直接把两个儿子的sum与自己的长度1全部加上后

再判断连接的地方是否相同,如果相同就减去多加的(这个地方可能说不清楚,但一看代码就明白了)

然后当前结点的lco就是左儿子的lco,rco就是右儿子的rco

还要注意如果没有左右儿子,就千万不要转移,否则会出问题,lco和rco会转移错误

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define db double
  4. #define ld long double
  5. const int MAXN=100000+10;
  6. int n,m;
  7. #define lc(x) ch[(x)][0]
  8. #define rc(x) ch[(x)][1]
  9. struct LCT{
  10. int ch[MAXN][2],fa[MAXN],rev[MAXN],sum[MAXN],lco[MAXN],rco[MAXN],pnt[MAXN],stack[MAXN],cnt,col[MAXN];
  11. inline bool nroot(int x)
  12. {
  13. return lc(fa[x])==x||rc(fa[x])==x;
  14. }
  15. inline void reverse(int x)
  16. {
  17. std::swap(lc(x),rc(x));
  18. std::swap(lco[x],rco[x]);
  19. rev[x]^=1;
  20. }
  21. inline void paint(int x,int c)
  22. {
  23. sum[x]=1;
  24. pnt[x]=col[x]=lco[x]=rco[x]=c;
  25. }
  26. inline void pushup(int x)
  27. {
  28. sum[x]=sum[lc(x)]+sum[rc(x)]+1;
  29. if(lc(x)&&rc(x))sum[x]=sum[x]-(rco[lc(x)]==col[x])-(col[x]==lco[rc(x)]);
  30. else if(lc(x))sum[x]=sum[x]-(rco[lc(x)]==col[x]);
  31. else if(rc(x))sum[x]=sum[x]-(col[x]==lco[rc(x)]);
  32. lco[x]=rco[x]=col[x];
  33. if(lc(x))lco[x]=lco[lc(x)];
  34. if(rc(x))rco[x]=rco[rc(x)];
  35. }
  36. inline void pushdown(int x)
  37. {
  38. if(pnt[x])
  39. {
  40. if(lc(x))paint(lc(x),pnt[x]);
  41. if(rc(x))paint(rc(x),pnt[x]);
  42. pnt[x]=0;
  43. }
  44. if(rev[x])
  45. {
  46. if(lc(x))reverse(lc(x));
  47. if(rc(x))reverse(rc(x));
  48. rev[x]=0;
  49. }
  50. }
  51. inline void rotate(int x)
  52. {
  53. int f=fa[x],p=fa[f],c=(rc(f)==x);
  54. if(nroot(f))ch[p][rc(p)==f]=x;
  55. fa[ch[f][c]=ch[x][c^1]]=f;
  56. fa[ch[x][c^1]=f]=x;
  57. fa[x]=p;
  58. pushup(f);
  59. pushup(x);
  60. }
  61. inline void splay(int x)
  62. {
  63. cnt=0;
  64. stack[++cnt]=x;
  65. for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
  66. while(cnt)pushdown(stack[cnt--]);
  67. for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
  68. if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
  69. pushup(x);
  70. }
  71. inline void access(int x)
  72. {
  73. for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
  74. }
  75. inline void makeroot(int x)
  76. {
  77. access(x);splay(x);reverse(x);
  78. }
  79. inline void split(int x,int y)
  80. {
  81. makeroot(x);access(y);splay(y);
  82. }
  83. inline void link(int x,int y)
  84. {
  85. makeroot(x);fa[x]=y;
  86. }
  87. };
  88. LCT T;
  89. #undef lc
  90. #undef rc
  91. inline void read(int &x)
  92. {
  93. int data=0,w=1;
  94. char ch=0;
  95. while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
  96. if(ch=='-')w=-1,ch=getchar();
  97. while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar();
  98. x=data*w;
  99. }
  100. inline void write(int x,char c='\0')
  101. {
  102. if(x<0)putchar('-'),x=-x;
  103. if(x>9)write(x/10);
  104. putchar(x%10+'0');
  105. if(c!='\0')putchar(c);
  106. }
  107. template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
  108. template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
  109. template<typename T> inline T min(T x,T y){return x<y?x:y;}
  110. template<typename T> inline T max(T x,T y){return x>y?x:y;}
  111. int main()
  112. {
  113. read(n);read(m);
  114. for(register int i=1;i<=n;++i)
  115. {
  116. int color;
  117. read(color);
  118. T.col[i]=T.lco[i]=T.rco[i]=color;
  119. T.sum[i]=1;
  120. }
  121. for(register int i=1;i<n;++i)
  122. {
  123. int u,v;
  124. read(u);read(v);
  125. T.link(u,v);
  126. }
  127. while(m--)
  128. {
  129. char opt[2];
  130. scanf("%s",opt);
  131. if(opt[0]=='C')
  132. {
  133. int a,b,c;
  134. read(a);read(b);read(c);
  135. T.split(a,b);T.paint(b,c);
  136. }
  137. if(opt[0]=='Q')
  138. {
  139. int a,b;
  140. read(a);read(b);
  141. T.split(a,b);
  142. write(T.sum[b],'\n');
  143. }
  144. }
  145. return 0;
  146. }

【刷题】BZOJ 2243 [SDOI2011]染色的更多相关文章

  1. BZOJ 2243: [SDOI2011]染色 [树链剖分]

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6651  Solved: 2432[Submit][Status ...

  2. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4637  Solved: 1726[Submit][Status ...

  3. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  4. bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 7925  Solved: 2975[Submit][Status ...

  5. bzoj 2243: [SDOI2011]染色 (树链剖分+线段树 区间合并)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9854  Solved: 3725[Submit][Status ...

  6. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  7. BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

    2243: [SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数 ...

  8. bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)

    [bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询 ...

  9. 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告

    [SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...

  10. BZOJ 2243 [SDOI2011]染色 (树链剖分)(线段树区间修改)

    [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6870  Solved: 2546[Submit][Status][Disc ...

随机推荐

  1. docker-compose 部署 EFK

    信息: Docker版本($ docker --version):Docker版本18.06.1-ce,版本e68fc7a 系统信息($ cat /etc/centos-release):CentOS ...

  2. STM平台增加性能测试/稳定性测试部分【一】

    前置 我之前写了一个接口自动化平台的,后期因为一个原因删除了. 现在,在此平台的基础上,我又增加了性能/稳定性的功能 它的前端大概是这样: 数据解析: 图表展示: 我将稳定性及性能归与一套方案去编写, ...

  3. HTML学习1-Dom之事件绑定

    事件: 1.注册事件 a. <div onxxxx=””></div> b. document  .onxxxx= function()  //找到这个标签 2.this,触发 ...

  4. 使用Java EE 在eclipse 开发动态的Web工程(Java web项目)

    1.使用Java EE 在eclipse 开发动态的Web工程(Java web项目)1)开发开发选项切换到JavaEE2)可以在Windows->show view中找到package exp ...

  5. sqli-labs学习笔记 DAY7

    DAY7 sqli-labs阶段总结 基本步骤 判断是否报错 判断闭合符号 判断注入类型 构建payload 手工注入或者编写脚本 基本注入类型 报错型注入 floor公式(结果多出一个1):and ...

  6. MegaCli64/MegaCli命令详解

    基础命令学习目录首页 MegaCli64 -LDInfo -Lall -aALL这个命令能看到RAID的状态MegaCli64 -LDSetProp ForcedWB -L0 -a0MegaCli64 ...

  7. hive对于lzo文件处理异常Caused by: java.io.IOException: Compressed length 842086665 exceeds max block size 67108864 (probably corrupt file)

    hive查询lzo数据格式文件的表时,抛 Caused by: java.io.IOException: Compressed length 842086665 exceeds max block s ...

  8. Django_rest_framework_Serializer

    序列化Serializer 序列化用于对用户请求数据进行验证和数据进行序列化(为了解决queryset序列化问题). 那什么是序列化呢?序列化就是把对象转换成字符串,反序列化就是把字符串转换成对象 m ...

  9. C++ Style Languages: C++, Objective-C, Java, C#

    Hyperpolyglot.org From Hyperpolyglot.org C++ Style Languages: C++, Objective-C, Java, C# a side-by-s ...

  10. java.util.ConcurrentModificationException: null

    是因为在map.foreach中又put新的值了 在map.foreach中可能是不可以增删改