2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 9012  Solved: 3375
[Submit][Status][Discuss]

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<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

Source

第一轮day1

树链剖分+线段树
操作还是常规的区间修改 但是要注意区间合并的时候,颜色段数量的合并
在树的路径上合并区间时,有点不好处理区间左右端点,于
是我们把u->v拆成u->lca lca->v
这样区间更新端点就是同向的,即每次查询可以把一端统一地作为更新端点
由于u->lca lca->v左右端点必定重合 所以 最后答案减一

sb的我update忘了pushup调了1h

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #define ls u<<1
  6. #define rs ls|1
  7. #define ll long long
  8. #define N 100050
  9. using namespace std;
  10. int n,m,tot,cnt,a[N],fa[N][20],tp[N],siz[N],hd[N];
  11. int dep[N],tid[N],son[N],v[N];
  12. struct edge{int v,next;}e[N<<1];
  13. struct node{int l,r,sum,lz;}t[N<<2];
  14. void adde(int u,int v){
  15. e[++tot].v=v;
  16. e[tot].next=hd[u];
  17. hd[u]=tot;
  18. }
  19. void dfs1(int u,int pre){
  20. dep[u]=dep[pre]+1;fa[u][0]=pre;siz[u]=1;
  21. for(int j=1;(1<<j)<dep[u];j++)
  22. fa[u][j]=fa[fa[u][j-1]][j-1];
  23. for(int i=hd[u];i;i=e[i].next){
  24. int v=e[i].v;
  25. if(v==pre)continue;
  26. dfs1(v,u);siz[u]+=siz[v];
  27. if(siz[v]>siz[son[u]])son[u]=v;
  28. }
  29. }
  30. void dfs2(int u,int anc){
  31. if(!u)return;
  32. tid[u]=++cnt;v[cnt]=a[u];tp[u]=anc;
  33. dfs2(son[u],anc);
  34. for(int i=hd[u];i;i=e[i].next){
  35. int v=e[i].v;
  36. if(v==fa[u][0]||v==son[u])continue;
  37. dfs2(v,v);
  38. }
  39. }
  40. int lca(int x,int y){
  41. if(x==y)return x;
  42. if(dep[x]<dep[y])swap(x,y);
  43. for(int i=18;~i;i--)
  44. if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
  45. if(x==y)return x;
  46. for(int i=18;~i;i--){
  47. if(fa[x][i]==fa[y][i])continue;
  48. x=fa[x][i];y=fa[y][i];
  49. }
  50. return fa[x][0];
  51. }
  52.  
  53. void pushup(int u){
  54. t[u].sum=t[ls].sum+t[rs].sum;
  55. t[u].l=t[ls].l;t[u].r=t[rs].r;
  56. if(t[ls].r==t[rs].l)t[u].sum--;
  57. }
  58. void pushdown(int u){
  59. if(t[u].lz==-1)return;
  60. t[ls].l=t[ls].r=t[ls].lz=t[u].lz;
  61. t[rs].l=t[rs].r=t[rs].lz=t[u].lz;
  62. t[ls].sum=t[rs].sum=1;
  63. t[u].lz=-1;
  64. }
  65. void build(int u,int l,int r){
  66. t[u].lz=-1;
  67. if(l==r){
  68. t[u].l=t[u].r=v[l];
  69. t[u].sum=1;return;
  70. }
  71. int mid=l+r>>1;
  72. build(ls,l,mid);
  73. build(rs,mid+1,r);
  74. pushup(u);
  75. }
  76. node query(int u,int L,int R,int l,int r){
  77. if(l<=L&&R<=r)return t[u];
  78. pushdown(u);node ret;
  79. int mid=L+R>>1,fg=0;
  80. if(l<=mid)ret=query(ls,L,mid,l,r),fg=1;
  81. if(r>mid){
  82. node tmp=query(rs,mid+1,R,l,r);
  83. if(!fg)ret=tmp;
  84. else{
  85. ret.sum+=tmp.sum;
  86. if(ret.r==tmp.l)ret.sum--;
  87. ret.r=tmp.r;
  88. }
  89. }
  90. return ret;
  91. }
  92. void update(int u,int L,int R,int l,int r,int c){
  93. if(l<=L&&R<=r){
  94. t[u].lz=t[u].l=t[u].r=c;
  95. t[u].sum=1;return;
  96. }
  97. pushdown(u);
  98. int mid=L+R>>1;
  99. if(l<=mid)update(ls,L,mid,l,r,c);
  100. if(r>mid)update(rs,mid+1,R,l,r,c);
  101. pushup(u);
  102. }
  103. node jump(int x,int y,int val,int op){
  104. int fx=tp[x],fy=tp[y];node ret;
  105. ret.l=ret.r=ret.sum=0;
  106. while(fx!=fy){
  107. if(op)update(1,1,cnt,tid[fx],tid[x],val);
  108. else{
  109. node tmp=query(1,1,cnt,tid[fx],tid[x]);
  110. ret.sum+=tmp.sum;
  111. if(tmp.r==ret.l)ret.sum--;
  112. ret.l=tmp.l;
  113. }
  114. x=fa[fx][0];fx=tp[x];
  115. }
  116. if(dep[x]>dep[y])swap(x,y);
  117. if(op)update(1,1,cnt,tid[x],tid[y],val);
  118. else{
  119. node tmp=query(1,1,cnt,tid[x],tid[y]);
  120. ret.sum+=tmp.sum;
  121. if(tmp.r==ret.l)ret.sum--;
  122. ret.l=tmp.l;
  123. }
  124. return ret;
  125. }
  126. int main(){
  127. scanf("%d%d",&n,&m);
  128. for(int i=1;i<=n;i++)
  129. scanf("%d",&a[i]);
  130. for(int i=1;i<n;i++){
  131. int a,b;
  132. scanf("%d%d",&a,&b);
  133. adde(a,b);adde(b,a);
  134. }
  135. dfs1(1,0);dfs2(1,1);
  136. build(1,1,cnt);
  137. int x,y,c;char s[2];
  138. while(m--){
  139. scanf("%s%d%d",s,&x,&y);
  140. int anc=lca(x,y);
  141. if(s[0]=='C'){
  142. scanf("%d",&c);
  143. jump(x,anc,c,1);
  144. jump(y,anc,c,1);
  145. }
  146. else{
  147. node t1,t2;
  148. t1=jump(x,anc,0,0);
  149. t2=jump(y,anc,0,0);
  150. printf("%d\n",t1.sum+t2.sum-1);
  151. }
  152. }
  153. return 0;
  154. }

bzoj2243[SDOI2011]染色 树链剖分+线段树的更多相关文章

  1. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

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

  2. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  3. B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

  4. 2243: [SDOI2011]染色 树链剖分+线段树染色

    给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  7. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  8. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  9. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

随机推荐

  1. iOS中CocoaPods的安装及错误详解

    什么是CocoaPods CocoaPods是OS X和iOS下的一个第三类库管理工具,通过CocoaPods工具我们可以为项目添加被称为"Pods"的依赖库(这些类库必须是Coc ...

  2. 第四十六条:for-each循环优先于传统的for循环

    for(Elements e : list) { //doSomeThing-- }

  3. Solr搜索引擎搭建详细过程

    1    什么是solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器.Solr可以独立运行在Jetty.Tomcat等这些Servlet容器中 ...

  4. nyoj 对决

    对决 时间限制:1000 ms  |  内存限制:65535 KB 难度:0   描述 Topcoder 招进来了 n 个新同学,Yougth计划把这个n个同学分成两组,要求每组中每个人必须跟另一组中 ...

  5. Python爬虫基本原理

    爬虫基本原理 1. 什么是爬虫 请求网站并提取数据的自动化程序. 2. 爬虫基本流程 发起请求 通过HTTP库向目标站点发起请求,即发送一个Request,请求可以包含额外的headers等信息,等待 ...

  6. 不允许用(a+b)/2这种方式求两个数的均值;如下程序在Linux和32位集成开发环境中运行

    #define MAX(a,b) ((a)>(b)?(a):(b)) #include<stdio.h> int main() { int a = 10; int b = 20; i ...

  7. VS 2008 开发WinCE程序 编译部署速度慢的解决办法

    1.找到以下文件 C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.CompactFramework.Common.targets 2.用记事本打开该 ...

  8. MQTT和paho(一)

    参考链接:http://blog.csdn.net/yangzl2008/article/details/8861069 一.mqtt 1.简单介绍 http://mqtt.org/software ...

  9. 单点登录实现机制:web-sso

    参考链接,感谢作者:https://zm10.sm-tc.cn/?src=l4uLj8XQ0IiIiNGckZ2TkJiM0ZyQktCZlo2Mi5uNmp6S0I/QysrJyszPztGXi5K ...

  10. zuul入门(1)zuul 的概念和原理

    一.zuul是什么 zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用. Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架. ...