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]之间。

第一眼看上去肯定是树链剖分,然后就是想怎么用线段树维护区间色段。

我们用线段树维护一个区间最左边的颜色,最右边的颜色,和颜色段数。如果一个节点的左儿子的右颜色和右儿子的左颜色相同,那么它的色段数是左+右-1,否则是左+右。

但是在查询时一定要注意,跑完每一条重链,和下一条重链中的轻链时,他们在线段树上并不是一起查询的。我们需要单点找出当前重链的顶端和下一个重链的底端的颜色,如果颜色相同,那么ans-1.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define in(a) a=read()
#define REP(i,k,n) for(int i=k;i<=n;i++)
#define MAXN 100010
using namespace std;
inline int read(){
int x=,f=;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
f=-;
for(;isdigit(ch);ch=getchar())
x=x*+ch-'';
return x*f;
}
int n,m,a,b,d;
char c;
int input[MAXN];
int total,head[MAXN],nxt[MAXN<<],to[MAXN<<];
int depth[MAXN],size[MAXN],son[MAXN],f[MAXN];
int cnt,dfn[MAXN],top[MAXN],link[MAXN];
struct node{
int l,r,lc,rc,s,lt;
}tree[MAXN<<];
inline void adl(int a,int b){
total++;
to[total]=b;
nxt[total]=head[a];
head[a]=total;
return ;
}
inline void getson(int u,int fa){//得到重儿子
size[u]=;
for(int e=head[u];e;e=nxt[e])
if(to[e]!=fa){
depth[to[e]]=depth[u]+;
f[to[e]]=u;
getson(to[e],u);
size[u]+=size[to[e]];
if(!son[u] || size[to[e]]>size[son[u]]) son[u]=to[e];
}
return ;
}
inline void getdfn(int u,int t){//得到重边
top[u]=t;
dfn[u]=++cnt;
link[cnt]=u;
if(!son[u]) return ;
getdfn(son[u],t);
for(int e=head[u];e;e=nxt[e])
if(to[e]!=f[u] && to[e]!=son[u])
getdfn(to[e],to[e]);
return ;
}
inline void build(int i,int l,int r){//建树
tree[i].l=l;
tree[i].r=r;
if(l==r){
tree[i].s=,tree[i].lc=tree[i].rc=input[link[l]];
return ;
}
int mid=(l+r)>>;
build(i<<,l,mid);
build(i<<|,mid+,r);
if(tree[i<<].rc==tree[i<<|].lc) tree[i].s=tree[i<<].s+tree[i<<|].s-;
else tree[i].s=tree[i<<].s+tree[i<<|].s;
tree[i].lc=tree[i<<].lc;
tree[i].rc=tree[i<<|].rc;
}
inline void pushdown(int i){//下传懒标记
if(!tree[i].lt) return ;
int k=tree[i].lt;
tree[i<<].s=tree[i<<|].s=;
tree[i<<].lc=tree[i<<].rc=tree[i<<|].lc=tree[i<<|].rc=k;
tree[i<<].lt=tree[i<<|].lt=k;
tree[i].lt=;
return ;
}
inline void add(int i,int l,int r,int k){//修改颜色
if(tree[i].l>=l && tree[i].r<=r){
tree[i].s=;
tree[i].lt=tree[i].lc=tree[i].rc=k;
return ;
}
pushdown(i);
if(tree[i<<].r>=l) add(i<<,l,r,k);
if(tree[i<<|].l<=r) add(i<<|,l,r,k);
if(tree[i<<].rc==tree[i<<|].lc) tree[i].s=tree[i<<].s+tree[i<<|].s-;
else tree[i].s=tree[i<<].s+tree[i<<|].s;
tree[i].lc=tree[i<<].lc;
tree[i].rc=tree[i<<|].rc;
return ;
}
inline void updates(int x,int y,int z){//枚举两点间每一条重边
int tx=top[x],ty=top[y];
while(tx!=ty){
if(depth[tx]<depth[ty]) swap(tx,ty),swap(x,y);
add(,dfn[tx],dfn[x],z);
x=f[tx];
tx=top[x],ty=top[y];
}
if(depth[x]<depth[y]) swap(x,y);
add(,dfn[y],dfn[x],z);
}
inline int query(int i,int l,int r){//区间查询
int sum=;
if(tree[i].l>=l && tree[i].r<=r) return tree[i].s;
pushdown(i);
if(tree[i<<].r>=l) sum+=query(i<<,l,r);
if(tree[i<<|].l<=r) sum+=query(i<<|,l,r);
if(tree[i<<].r>=l && tree[i<<|].l<=r && tree[i<<].rc==tree[i<<|].lc) sum--;
return sum;
}
inline int getcolor(int i,int dis){//查询单点颜色
if(tree[i].l==tree[i].r) return tree[i].lc;
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>;
if(dis<=mid) return getcolor(i<<,dis);
else return getcolor(i<<|,dis);
}
inline int getsum(int x,int y){//枚举查询时两点间的重边
int tx=top[x],ty=top[y],ans=;
while(tx!=ty){
if(depth[tx]<depth[ty]) swap(tx,ty),swap(x,y);
ans+=query(,dfn[tx],dfn[x]);
if(getcolor(,dfn[tx])==getcolor(,dfn[f[tx]])) ans--;//看轻边两点的颜色是否相同
x=f[tx];
tx=top[x],ty=top[y];
}
if(depth[x]<depth[y]) swap(x,y);
ans+=query(,dfn[y],dfn[x]);
return ans;
}
int main(){
in(n),in(m);
REP(i,,n) in(input[i]);
REP(i,,n-) in(a),in(b),adl(a,b),adl(b,a);
depth[]=;
getson(,);
getdfn(,);
build(,,n);
REP(i,,m){
cin>>c;
if(c=='C') in(a),in(b),in(d),updates(a,b,d);
if(c=='Q') in(a),in(b),printf("%d\n",getsum(a,b));
}
}

bzoj2243 染色的更多相关文章

  1. 刷题总结——bzoj2243染色

    题目: 题目背景 SDOI2011 DAY1 T3 题目描述 给定一棵有 n 个节点的无根树和 m 个操作,操作有 2 类:1.将节点 a 到节点 b 路径上所有点都染成颜色 c :2.询问节点 a  ...

  2. HDU5892~HDU5901 2016网络赛沈阳

    A.题意: 有一个n×n的格子, 有50种怪物. 有m个操作, 每次操作会往一个矩形区域放怪物, 每个格子放相同数目的怪物, 或者查询当前50种怪物的奇偶性. 分析:用2^50表示怪物的奇偶,然后就是 ...

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

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

  4. BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

  5. BZOJ2243 SDOI2011 染色 【树链剖分】

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

  6. 【BZOJ2243】染色(树链剖分)

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

  7. bzoj2243树链剖分+染色段数

    终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...

  8. bzoj-2243 2243: [SDOI2011]染色(树链剖分)

    题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6267  Solved: 2291 Descript ...

  9. [bzoj2243][SDOI2011]染色

    Description 给定一棵有$n$个节点的无根树和$m$个操作,操作有$2$类: 1.将节点$a$到节点$b$路径上所有点都染成颜色$c$; 2.询问节点$a$到节点$b$路径上的颜色段数量(连 ...

随机推荐

  1. ASP.NET MVC 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁

    在开发程序的过程中,稍微不注意就会隐含有sql注入的危险.今天我就来说下,ASP.NET mvc 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁.不用每下地方对参数的值都进行检 ...

  2. avalonJS-源码阅读(二)

    上一篇文章讲述的avalon刷页面所用到的几个函数.这篇则是主要讲avalon对刷DOM刷出来的avalon自定义属性如何处理的. 目录[-] avalon页面处理(2) 数据结构 解析avalon标 ...

  3. 关于Java中final关键字的详细介绍

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  4. 十五、springboot集成定时任务(Scheduling Tasks)(二)之(线程配置)

    配置类: /** * 定时任务线程配置 * */ @Configuration public class SchedulerConfig implements SchedulingConfigurer ...

  5. Golang新起航!(编译安装go)

    别废话,直接上~ linux下安装GO1.8 1.下载go的版本 国内地址源:https://dl.gocn.io/ 在这里选择源码的方式安装,在安装go的时候是需要gcc的,所以你的linux系统需 ...

  6. KVM和远程管理工具virt-manager

    kvm在server端的部署(针对rhel6系统,可以构建本地更新源) 注意:如果只是安装管理工具,可以试试直接执行8步骤 1.对服务器实行kvm虚拟化首先需要确认服务器的物理硬件是否支持 cat / ...

  7. Java基础83 JSP标签及jsp自定义标签(网页知识)

    1.JSP标签 替代jsp脚本,用于jsp中执行java代码1.1.内置标签:  <jsp:forward></jsp:forward>  相当于:request.getReu ...

  8. Robots.txt 不让搜索引擎收录网站的方法

    有没有担心过自己的隐私会在强大的搜索引擎面前无所遁形?想象一下,如果要向世界上所有的人公开你的私人日记,你能接受吗?的确是很矛盾的问题,站长们大都忧虑“如何让搜索引擎收录的我的网站?”,而我们还是要研 ...

  9. 一个带bash,带glibc,中国时区,非root用户可运行crond命令的基于alpine镜像的Dockerfile

    这个镜像现在说起来简单, 带bash(增加执行脚本的兼容性,带GLIBC,中国时区,非root用户可运行crond命令-安全) 但让我开始陷入时,真的让我有段时间有点爆了. 比如,将filebeat文 ...

  10. html-图片热点和网页划区

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...