博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 2243: [SDOI2011]染色
阅读量:4311 次
发布时间:2019-06-06

本文共 2571 字,大约阅读时间需要 8 分钟。

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

首先用树剖和线段树处理

这时线段树记录的信息有a[x].l表示这段区间最左边的颜色编号,a[x].r表示这段区间最右边的颜色编号,a[x].s表示颜色数

在push up的时候,a[x].s=a[ls].s+a[rs].s,如果a[ls].r==a[rs].l就说明重复计入了一个,那么就要讲a[x].s--;

在查询答案时也要注意这一点,对于分别查询的两个区间之间要进行颜色是否相同的判断,对于链与链之间也要进行相同的判断。

#include
#include
#define ls x<<1#define rs x<<1|1using namespace std;const int N=1e5+5;struct Y{ int v,f,n;}y[N<<1];struct A{ int l,r,s,lz; void fz(int g) { l=r=lz=g; s=1; }}a[N<<2];int s,ss,siz[N],fa[N],co[N],dfn[N],tou[N],hson[N],n;void add(int u,int v){ y[++s].v=v; y[s].n=y[u].f; y[u].f=s;}void dfs1(int u){ siz[u]=1; for(int i=y[u].f;i;i=y[i].n) if(y[i].v!=fa[u]) { fa[y[i].v]=u; dfs1(y[i].v); siz[u]+=siz[y[i].v]; if(siz[y[i].v]>siz[hson[u]]) hson[u]=y[i].v; }}void dfs2(int u,int to){ dfn[u]=++ss; tou[u]=to; if(hson[u]) dfs2(hson[u],to); for(int i=y[u].f;i;i=y[i].n) if(y[i].v!=hson[u]&&y[i].v!=fa[u]) dfs2(y[i].v,y[i].v);}void pd(int x,int l,int r,int mid){ if(a[x].lz) { a[ls].fz(a[x].lz),a[rs].fz(a[x].lz); a[x].lz=0; }}void chan(int x,int l,int r,int ql,int qr,int z){ if(ql<=l&&r<=qr) a[x].fz(z); else { int mid=(l+r)>>1; pd(x,l,r,mid); if(ql<=mid) chan(ls,l,mid,ql,qr,z); if(qr>mid) chan(rs,mid+1,r,ql,qr,z); a[x].l=a[ls].l;a[x].r=a[rs].r; a[x].s=a[ls].s+a[rs].s; if(a[ls].r==a[rs].l) --a[x].s; }}int askk(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return a[x].s; int mid=(l+r)>>1,re=0; pd(x,l,r,mid); if(ql<=mid) re+=askk(ls,l,mid,ql,qr); if(qr>mid) re+=askk(rs,mid+1,r,ql,qr); if(ql<=mid&&qr>mid&&a[ls].r==a[rs].l) --re; return re;}int gc(int x,int l,int r,int wz){ if(l==r) return a[x].lz; int mid=(l+r)>>1; pd(x,l,r,mid); if(wz<=mid) return gc(ls,l,mid,wz); else return gc(rs,mid+1,r,wz);}int qu(int u,int v){ int re=0; while(tou[u]!=tou[v]) { if(dfn[u]

 

转载于:https://www.cnblogs.com/bzmd/p/9410945.html

你可能感兴趣的文章
绕任意单位轴旋转矩阵计算
查看>>
洛谷P2502[HAOI2006]旅行
查看>>
Linux 配置mail发送邮件
查看>>
Linux 正则
查看>>
织梦网站搬家,数据库无法导入的解决方法
查看>>
线程基础知识归纳
查看>>
CArray 的两种方式与类中包含指针情况
查看>>
ElasticSearch 自定义排序处理
查看>>
域的建立过程
查看>>
使用installer安装kbengine
查看>>
IOS 开发didFinishLaunchingWithOptions 设置启动View
查看>>
MyBank(自助银行)
查看>>
python机器学习-sklearn挖掘乳腺癌细胞(二)
查看>>
javascript中的函数节流和函数去抖
查看>>
异步函数的串行执行和并行执行
查看>>
Import Solution Error code :0x80048426
查看>>
Spring的注解@Qualifier小结
查看>>
目前最新版本ActiveMQ 5.15.3 和JDK版本有关的问题
查看>>
hdu 4513 吉哥系列故事——完美队形II
查看>>
ECSHOP让产品浏览历史按照先后进行排序
查看>>