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会转移错误

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXN=100000+10;
int n,m;
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
int ch[MAXN][2],fa[MAXN],rev[MAXN],sum[MAXN],lco[MAXN],rco[MAXN],pnt[MAXN],stack[MAXN],cnt,col[MAXN];
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
std::swap(lco[x],rco[x]);
rev[x]^=1;
}
inline void paint(int x,int c)
{
sum[x]=1;
pnt[x]=col[x]=lco[x]=rco[x]=c;
}
inline void pushup(int x)
{
sum[x]=sum[lc(x)]+sum[rc(x)]+1;
if(lc(x)&&rc(x))sum[x]=sum[x]-(rco[lc(x)]==col[x])-(col[x]==lco[rc(x)]);
else if(lc(x))sum[x]=sum[x]-(rco[lc(x)]==col[x]);
else if(rc(x))sum[x]=sum[x]-(col[x]==lco[rc(x)]);
lco[x]=rco[x]=col[x];
if(lc(x))lco[x]=lco[lc(x)];
if(rc(x))rco[x]=rco[rc(x)];
}
inline void pushdown(int x)
{
if(pnt[x])
{
if(lc(x))paint(lc(x),pnt[x]);
if(rc(x))paint(rc(x),pnt[x]);
pnt[x]=0;
}
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y)
{
makeroot(x);fa[x]=y;
}
};
LCT T;
#undef lc
#undef rc
inline void read(int &x)
{
int data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
inline void write(int x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
read(n);read(m);
for(register int i=1;i<=n;++i)
{
int color;
read(color);
T.col[i]=T.lco[i]=T.rco[i]=color;
T.sum[i]=1;
}
for(register int i=1;i<n;++i)
{
int u,v;
read(u);read(v);
T.link(u,v);
}
while(m--)
{
char opt[2];
scanf("%s",opt);
if(opt[0]=='C')
{
int a,b,c;
read(a);read(b);read(c);
T.split(a,b);T.paint(b,c);
}
if(opt[0]=='Q')
{
int a,b;
read(a);read(b);
T.split(a,b);
write(T.sum[b],'\n');
}
}
return 0;
}

【刷题】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. Android Library开发注意事项

    Android Library开发注意事项 App Module添加依赖Android Library时可以设置library的优先级, 在编译时,app按照library从低到高的优先级依次与每个l ...

  2. Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用

    Netty源码分析第一章:Netty启动流程   第四节:注册多路复用 回顾下以上的小节, 我们知道了channel的的创建和初始化过程, 那么channel是如何注册到selector中的呢?我们继 ...

  3. python打包成exe文件

    在cmd命令提示符窗口中输入pip install pyinstaller(在python3的环境下,假如不能安装的话,用pip3 install pyinstaller指令) 使用指令pyinsta ...

  4. 离线人脸识别 ArcFaceSharp -- ArcFace 2.0 SDK C#封装库分享

    ArcFaceSharp ArcFaceSharp 是ArcSoft 虹软 ArcFace 2.0 SDK 的一个 C# 封装库,为方便进行 C# 开发而封装.欢迎 Start & Fork. ...

  5. Linux 150命令之查看文件及内容处理命令 more split file diff paste wc dps2unix

    more命令 使用more命令显示more /var/log/boot.log-20171129文件,可以从图中看出,系统在显示满一个屏幕时暂停,使用空格可以翻页,使用Q键可以退出. split sp ...

  6. date命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/qmfsun/p/4598650.html date "+今天是%Y-%d-%m,现在是%H:%M:%S&qu ...

  7. RHEL6.4 xclock安装小记

    http://blog.sina.com.cn/s/blog_623630d50101tc67.html

  8. YQCB冲刺第二周第二天

    今天的任务依然为实现查看消费明细的功能. 遇到的问题为从数据库中分类读取,实现图标的显示. 站立会议为: 任务面板为:

  9. java 对象和基本数据类型 “==”区别

    “==”比较的是地址,牢记.1.对象.integer 是对象 Integer i1 = 20; Integer i2 = 20 ; System.out.println(i1 == i2); // t ...

  10. php 把数字转化为大写中文

    PHP 数字转大写中文 PHP入门小菜鸟一枚.下午要求写一个把数字转成大写中文的脚本,百度了一波,几十个博客和网站都是用的那四个代码,第一个运行不了,第二个有问题,不合要求,第三个第四个太长,懒得看, ...