2243: [SDOI2011] 染色

  Time Limit: 20 Sec
  Memory Limit: 512 MB

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 1

  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 1

  3
  1
  2

HINT

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

题目地址: BZOJ 2243: [SDOI2011]染色

题解:

     
  此题的关键是线段树记录的信息是什么
  线段树上记三个量:
  该段颜色段数,左端点颜色,右端点颜色
  在合并的时候段点颜色要特别小心仔细
  写法技巧和细节也很重要
  其余树链剖分
www.cnblogs.com/AGFghy/


AC代码

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,m,u,v,x,y,c,num,cnt;
int point[N<<1],next[N<<1],head[N];
int fa[N],dep[N],size[N],son[N],id[N],top[N];
int a[N],fc[N];
char pd[5];
struct node
{int lc,rc,v,lazy;
}tree[N<<2];
void add(int u,int v)
{point[++num]=v;next[num]=head[u];head[u]=num;
}
void dfs1(int now,int pre)
{fa[now]=pre;dep[now]=dep[pre]+1;size[now]=1;for (int i=head[now]; i; i=next[i]){int v=point[i];if (v==pre) continue;dfs1(v,now);size[now]+=size[v];if (size[v]>size[son[now]]) son[now]=v;}
}
void dfs2(int now,int topf)
{top[now]=topf;id[now]=++cnt;a[cnt]=fc[now]+1;if (!son[now]) return;dfs2(son[now],topf);for (int i=head[now]; i; i=next[i]){int v=point[i];if (v==fa[now] || v==son[now]) continue;dfs2(v,v);}
}
void pushup(int p)
{tree[p].lc=tree[p<<1].lc;tree[p].rc=tree[(p<<1)+1].rc;tree[p].v=tree[p<<1].v+tree[(p<<1)+1].v-(tree[p<<1].rc==tree[(p<<1)+1].lc);
}
void pushdown(int p)
{if (tree[p].lazy){tree[p<<1].lc=tree[p<<1].rc=tree[p<<1].lazy=tree[p].lazy; tree[p<<1].v=1;tree[(p<<1)+1].lc=tree[(p<<1)+1].rc=tree[(p<<1)+1].lazy=tree[p].lazy; tree[(p<<1)+1].v=1;tree[p].lazy=0;}
}
void build(int l,int r,int p)
{if (l==r){tree[p].lc=tree[p].rc=a[l];tree[p].v=1;return;}int mid=(l+r)>>1;build(l,mid,p<<1);build(mid+1,r,(p<<1)+1);pushup(p);
}
void update(int l,int r,int p,int s,int t,int c)
{if (l==s && r==t){tree[p].lc=tree[p].rc=tree[p].lazy=c;tree[p].v=1;return;}pushdown(p);int mid=(l+r)>>1;if (t<=mid) update(l,mid,p<<1,s,t,c);else if (s>mid) update(mid+1,r,(p<<1)+1,s,t,c);else{update(l,mid,p<<1,s,mid,c);update(mid+1,r,(p<<1)+1,mid+1,t,c);}pushup(p);
}
node query(int l,int r,int p,int s,int t)
{if (l==s && r==t) return tree[p];pushdown(p);int mid=(l+r)>>1;if (t<=mid) return query(l,mid,p<<1,s,t);else if (s>mid) return query(mid+1,r,(p<<1)+1,s,t);else{node res,s1,s2;s1=query(l,mid,p<<1,s,mid);   s2=query(mid+1,r,(p<<1)+1,mid+1,t);res.lc=s1.lc; res.rc=s2.rc;res.v=s1.v+s2.v-(s1.rc==s2.lc);return res;}
}
void cover(int x,int y,int c)
{while (top[x]!=top[y]){if (dep[top[x]]<dep[top[y]]) swap(x,y);update(1,n,1,id[top[x]],id[x],c);x=fa[top[x]];}if (dep[x]>dep[y]) swap(x,y);update(1,n,1,id[x],id[y],c);
}
int seg(int x,int y)
{int xc=-1,yc=-1,ans=0;node now;while (top[x]!=top[y]){if (dep[top[x]]<dep[top[y]]) swap(x,y),swap(xc,yc);now=query(1,n,1,id[top[x]],id[x]);ans+=now.v-(now.rc==xc);xc=now.lc; x=fa[top[x]];}if (dep[x]>dep[y]) swap(x,y),swap(xc,yc);now=query(1,n,1,id[x],id[y]);ans+=now.v-(now.lc==xc)-(now.rc==yc);return ans;
}
int main()
{scanf("%d%d",&n,&m);for (int i=1; i<=n; i++)scanf("%d",&fc[i]);for (int i=1; i<n; i++){scanf("%d%d",&u,&v);add(u,v); add(v,u);}dfs1(1,0);dfs2(1,1);build(1,n,1);while (m--){scanf("%s",pd);if (pd[0]=='C') {scanf("%d%d%d",&x,&y,&c);c++;cover(x,y,c);}if (pd[0]=='Q'){scanf("%d%d",&x,&y);printf("%d\n",seg(x,y));}}
}


转载于:https://www.cnblogs.com/AGFghy/p/9362865.html

BZOJ 2243: [SDOI2011]染色(树链剖分)相关推荐

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

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

  2. 洛谷 P2486 [SDOI2011]染色 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...

  3. BZOJ 2243: [SDOI2011]染色

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

  4. HDU 3966 POJ 3237 HYSBZ 2243 HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  5. BZOJ 4034 [HAOI2015]T2 树链剖分

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

  6. HYSBZ - 2243染色——树链剖分+线段树建树技巧

    [题目描述] HYSBZ - 2243染色 [题目分析] 我一直没有看清楚题,以为求的是路径上出现颜色的种类,然后就写了一个区间染色的线段树进行维护,过样例的时候才发现题读错了,人家要求的是路径上出现 ...

  7. BZOJ 4034: [HAOI2015]T2 树链剖分

    4034: [HAOI2015]T2 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操 ...

  8. bzoj 4127: Abs(树链剖分+线段树)

    4127: Abs Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 667  Solved: 225 [Submit][Status][Discuss ...

  9. BZOJ 2243 染色(树链剖分好题)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Stat ...

  10. BZOJ 2243 树链剖分

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 题意:中文题目 思路:树链剖分.首先考虑求区间颜色段数的问题, 我们可以用线段树维护 ...

最新文章

  1. openssl 从cer文件中提取公钥
  2. C语言实现了一个顺序表(附完整源码)
  3. php应用编程,极客编程必备的五大PHP开发应用_PHP
  4. SAP UI5应用访问OData metadata的url和Destination
  5. MySQL存储树形数据优化技笔记
  6. idea spring tomcat启动失败_技术篇 | 实用IDEA插件和工具系列
  7. javaScript一种优化模式-初始化时分支
  8. 第八章 linux磁盘与文件系统管理g
  9. scrapy-cluster scrapy集群建设
  10. mysql 实现字符串的拼接
  11. 多周期MIPS CPU硬布线控制器设计
  12. nios 双核 烧录_Nios程序烧写到EPCS方法
  13. haosou属于搜索引擎的_搜索引擎登录工具
  14. 鸿蒙OS可以装电脑吗,组装台式机可以装鸿蒙系统吗?
  15. mac废纸篓的如何还原?
  16. 计算机网络应用班级口号霸气押韵,跑操口号大全(精选50句)
  17. 实现对光网络的监控和光路切换 - MEMS 光开关
  18. jwplayer 如何从视频中截取图片
  19. JS判断浏览器版本(已解决IE11版本为Mozilla问题)
  20. [转帖]实时协同设计CAD平台

热门文章

  1. 专家:苹果有能力打造Mac芯片但不会去做
  2. 理解C语言——从小菜到大神的晋级之路(9)——多维数组
  3. [转]测试的三重境界
  4. Net设计模式实例之桥接模式( Bridge Pattern)(4)
  5. 老愤青也来说两句,也谈青年程序员如何进入职场
  6. CentOS6.6 32位 Minimal版本纯编译安装Nginx Mysql PHP Memcached
  7. FPGA系列之一:Cyclone V中的时钟资源
  8. linux下select,poll,epoll的使用与重点分析
  9. android中在java代码中设置Button按钮的背景颜色
  10. 【代码笔记】iOS-判断中英文混合的字符长度的两种方法