[bzoj2243][SDOI2011]染色
Description
给定一棵有$n$个节点的无根树和$m$个操作,操作有$2$类:
1.将节点$a$到节点$b$路径上所有点都染成颜色$c$;
2.询问节点$a$到节点$b$路径上的颜色段数量(连续相同颜色被认为是同一段),如$"112221"$由$3$段组成:$"11","222"和"1"$.
请你写一个程序依次完成这$m$个操作.
Input
第一行包含$2$个整数$n$和$m$,分别表示节点数和操作数.
第二行包含$n$个正整数表示$n$个节点的初始颜色.
下面$n-1$行每行包含两个整数$x$和$y$,表示$x$和$y$之间有一条无向边.
下面$m$行每行描述一个操作:
$”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,M\;\leq\;10^5,c\;\in\;z,c\;\in\;[0, 10^9]$.
Solution
树链剖分+线段树.
每次上移的时候判断相邻两段端点是否同色即可.
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100005
#define M 300005
using namespace std;
struct linetree{
int l,r,lc,rc,cnt;
}lt[M];
struct graph{
int nxt,to;
}e[M];
char c[2];
int g[N],a[N],w[N],n,m,u,v,k,l,cnt;
int f[N],p[N],dep[N],siz[N],son[N],top[N];
inline void addedge(int x,int y){
e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
}
inline void dfs1(int u){
int m=0;siz[u]=1;
for(int i=g[u];i;i=e[i].nxt)
if(!dep[e[i].to]){
f[e[i].to]=u;
dep[e[i].to]=dep[u]+1;
dfs1(e[i].to);
siz[u]+=siz[e[i].to];
if(siz[e[i].to]>m){
son[u]=e[i].to;
m=siz[e[i].to];
}
}
}
inline void dfs2(int u,int tp){
top[u]=tp;p[u]=++cnt;w[cnt]=a[u];
if(son[u]) dfs2(son[u],tp);
for(int i=g[u];i;i=e[i].nxt)
if(f[u]!=e[i].to&&e[i].to!=son[u])
dfs2(e[i].to,e[i].to);
}
inline void build(int u,int l,int r){
lt[u].l=l;lt[u].r=r;
if(lt[u].l<lt[u].r){
int lef=u<<1,rig=u<<1|1;
int mid=(lt[u].l+lt[u].r)>>1;
build(lef,l,mid);build(rig,mid+1,r);
lt[u].cnt=lt[lef].cnt+lt[rig].cnt;
if(lt[lef].rc==lt[rig].lc) --lt[u].cnt;
lt[u].lc=lt[lef].lc;lt[u].rc=lt[rig].rc;
}
else{
lt[u].cnt=1;lt[u].lc=lt[u].rc=w[lt[u].l];
}
}
inline void cover(int u,int l,int r,int k){
if(lt[u].l>=l&<[u].r<=r){
lt[u].lc=lt[u].rc=k;lt[u].cnt=1;
}
else if(lt[u].l<lt[u].r){
int lef=u<<1,rig=u<<1|1;
int mid=(lt[u].l+lt[u].r)>>1;
if(lt[u].cnt==1){
lt[lef].cnt=lt[rig].cnt=1;
lt[lef].lc=lt[lef].rc=lt[rig].lc=lt[rig].rc=lt[u].lc;
}
if(l<=mid) cover(lef,l,r,k);
if(r>mid) cover(rig,l,r,k);
lt[u].cnt=lt[lef].cnt+lt[rig].cnt;
if(lt[lef].rc==lt[rig].lc) --lt[u].cnt;
lt[u].lc=lt[lef].lc;lt[u].rc=lt[rig].rc;
}
}
inline int ask(int u,int l,int r){
if(lt[u].l>=l&<[u].r<=r)
return lt[u].cnt;
if(lt[u].l<lt[u].r){
int lef=u<<1,rig=u<<1|1,ret=0;
int mid=(lt[u].l+lt[u].r)>>1;
if(lt[u].cnt==1){
lt[lef].cnt=lt[rig].cnt=1;
lt[lef].lc=lt[rig].lc=lt[lef].rc=lt[rig].rc=lt[u].lc;
}
if(l<=mid) ret+=ask(lef,l,r);
if(r>mid) ret+=ask(rig,l,r);
if(l<=mid&&r>mid&<[lef].rc==lt[rig].lc) --ret;
return ret;
}
}
inline int col(int u,int x){
if(lt[u].l==x) return lt[u].lc;
if(lt[u].r==x) return lt[u].rc;
if(lt[u].l<lt[u].r){
int lef=u<<1,rig=u<<1|1;
int mid=(lt[u].l+lt[u].r)>>1;
if(lt[u].cnt==1){
lt[lef].cnt=lt[rig].cnt=1;
lt[lef].lc=lt[rig].lc=lt[lef].rc=lt[rig].rc=lt[u].lc;
}
if(x<=mid) return col(lef,x);
return col(rig,x);
}
}
inline void cov(int x,int y,int k){
int t;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
t=x;x=y;y=t;
}
cover(1,p[top[x]],p[x],k);
x=f[top[x]];
}
if(p[x]>p[y]){
t=x;x=y;y=t;
}
cover(1,p[x],p[y],k);
}
inline int q(int x,int y){
int ret=0,t;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
t=x;x=y;y=t;
}
ret+=ask(1,p[top[x]],p[x]);
if(col(1,p[top[x]])==col(1,p[f[top[x]]])) --ret;
x=f[top[x]];
}
if(p[x]>p[y]){
t=x;x=y;y=t;
}
ret+=ask(1,p[x],p[y]);
return ret;
}
inline int lca(int x,int y){
int t;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
t=x;x=y;y=t;
}
x=f[top[x]];
}
if(p[x]>p[y]){
t=x;x=y;y=t;
}
return x;
}
inline void Aireen(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int i=1,x,y;i<n;++i){
scanf("%d%d",&x,&y);
addedge(x,y);addedge(y,x);
}
dep[1]=1;dfs1(1);
cnt=0;dfs2(1,1);
build(1,1,n);
while(m--){
scanf("%s%d%d",c,&u,&v);
if(c[0]=='C'){
scanf("%d",&k);cov(u,v,k);
}
else{
l=lca(u,v);
printf("%d\n",q(u,v));
}
}
}
int main(){
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
Aireen();
fclose(stdin);
fclose(stdout);
return 0;
}
[bzoj2243][SDOI2011]染色的更多相关文章
- BZOJ2243 SDOI2011 染色 【树链剖分】
BZOJ2243 SDOI2011 染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- BZOJ2243[SDOI2011]染色——树链剖分+线段树
题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221 ...
- [BZOJ2243][SDOI2011]染色 解题报告|树链剖分
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- BZOJ2243: [SDOI2011]染色(树链剖分/LCT)
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...
- bzoj2243: [SDOI2011]染色--线段树+树链剖分
此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...
- BZOJ2243——[SDOI2011]染色
1.题目大意:给个树,然后树上每个点都有颜色,然后会有路径的修改,有个询问,询问一条路径上的颜色分成了几段 2.分析:首先这个修改是树剖可以做的,对吧,但是这个分成了几段怎么搞呢,我们的树剖的不是要建 ...
- bzoj2243 sdoi2011 染色 paint
明明是裸树剖 竟然调了这么久好蛋疼 大概是自己比较水的原因吧 顺便+fastio来gangbang #include<iostream> #include<cstring> # ...
随机推荐
- ubuntu下crontab编辑方法的设定
在ubuntu下,首次编辑crontab计划任务的时候,会提示让选择编辑器.由于对nano编辑器不是很熟悉,若是选择nova编辑的话,会有些麻烦.可以重置编辑器,方法如下:[root@wang ~]# ...
- Python的高级特性6:使用__slots__真的能省很多内存
在伯乐在线上看到了这篇文章,用Python的 __slots__ 节省9G内存,于是想测试下,对单个类,用__slots__节省内存效果会不会明显. 看完这个例子后,我们也会明白__slots__是用 ...
- C#将JSON字符串对象序列化与反序列化
C#将对象序列化成JSON字符串 public string GetJsonString() { List<Product> products = new List<Product& ...
- 去掉Win7资源管理器左侧导航窗格中的收藏夹、库等的方法
去掉Win7资源管理器的收藏夹/库/家庭组/网络的方法 将Windows 7资源管理器左侧导航窗格中的收藏夹.库.家庭组.网络全部去掉,只剩下计算机, 以收藏夹为例作简要说明. 首先打开注册表编辑器, ...
- 2016.11.14测试 长乐一中2014NOIP复赛模拟题 第一题。
1.正确答案 [题目描述] 小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案. "吔,我的答案和你都不一样!",小Y说道,"我们去找神犇们问答案吧&q ...
- DefaultFilesMiddleware中间件如何显示默认页面
DefaultFilesMiddleware中间件如何显示默认页面 DefaultFilesMiddleware中间件的目的在于将目标目录下的默认文件作为响应内容.我们知道,如果直接请求的就是这个默认 ...
- hessian学习
hessian是一个采用二进制格式传输的服务框架,相对传统soap web service,更轻量,更快速.官网地址:http://hessian.caucho.com/ 目前已经支持N多语言,包括: ...
- 牛X的CSS3
See the Pen Dot Wave by Rich Howell (@roborich) on CodePen
- SQL基础之数据库快照
1.认识快照 如名字一样,数据库快照就可以理解为数据库某一时刻的照片,它记录了此时数据库的数据信息.如果要认识快照的本质,那就要了解快照的工作原理.当我们执行t-sql创建快照后,此时就会创建一个或多 ...
- 论javascript中的原始值和对象
javascript将数据类型分为两类:原始值(undefined.null.布尔值.数字和字符串),对象(对象.函数和数组) 论点:原始值不可以改变,对象可以改变:对象为引用类型: '原始值不可以改 ...