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,表示xy之间有一条无向边。

下面 行每行描述一个操作:

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


My Solution

一道可爱的树链剖分题啊

注意区间合并和树剖中的calc即可

 #include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; inline int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} inline char rea(){
char ch;
while((ch=getchar())!='Q'&&ch!='C');
return ch;
} struct edge{
int to,next;
edge(int to=,int next=):
to(to),next(next){}
}; struct segment{
int l,r,lc,rc,sum,tag;
}; const int maxn=1e5+; edge edges[maxn<<];
segment tre[maxn<<];
int n,m,cnt=,root;
//si1,si2表示query操作中取到的最高和最低颜色
int si1,si2,LL,RR;
int head[maxn],data[maxn];
int siz[maxn],fat[maxn],son[maxn],dep[maxn],id[maxn],id_[maxn],top[maxn]; inline void add_edge(int from,int to){
edges[++cnt]=edge(to,head[from]); head[from]=cnt;
edges[++cnt]=edge(from,head[to]); head[to]=cnt;
} void init(){
n=read(); m=read();
for(int i=;i<=n;i++) data[i]=read();
int from,to; cnt=;
for(int i=;i<n;i++){
from=read(); to=read();
add_edge(from,to);
}
} void dfs_1(int x,int fa){
siz[x]=;
dep[x]=dep[fa]+;
fat[x]=fa;
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fa){
dfs_1(edges[ee].to,x);
siz[x]+=siz[edges[ee].to];
if(!son[x]||siz[edges[ee].to]>siz[son[x]]) son[x]=edges[ee].to;
}
} void dfs_2(int x,int first){
top[x]=first;
id[x]=++cnt;
id_[cnt]=x;
if(!son[x]) return;
dfs_2(son[x],first);
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fat[x]&&edges[ee].to!=son[x]) dfs_2(edges[ee].to,edges[ee].to);
} void push_up(int x){
int lson=x<<,rson=lson|;
tre[x].lc=tre[lson].lc;
tre[x].rc=tre[rson].rc;
tre[x].sum=tre[lson].sum+tre[rson].sum-(tre[lson].rc==tre[rson].lc?:);
} void build(int x,int l,int r){
tre[x].l=l; tre[x].r=r;
if(l==r){
tre[x].lc=tre[x].rc=data[id_[l]];
tre[x].sum=;
return;
}
int mid=(l+r)>>;
build(x<<,l,mid); build(x<<|,mid+,r);
push_up(x);
} void push_down(int x){
int lson=x<<,rson=lson|;
int &c=tre[x].tag;
tre[lson].tag=tre[rson].tag=tre[lson].lc=
tre[lson].rc=tre[rson].lc=tre[rson].rc=c;
tre[lson].sum=; tre[rson].sum=;
c=;
} void make(){
root=; dfs_1(root,);
cnt=; dfs_2(root,root);
build(,,n);
} void update(int x,int L,int R,int c){
if(L<=tre[x].l&&tre[x].r<=R){
tre[x].lc=tre[x].rc=tre[x].tag=c;
tre[x].sum=;
return;
} if(tre[x].tag) push_down(x); int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) update(x<<,L,R,c);
else if(L>mid) update(x<<|,L,R,c);
else{
update(x<<,L,mid,c);
update(x<<|,mid+,R,c);
}
push_up(x);
} int query_sum(int x,int L,int R){
if(tre[x].l==LL) si1=tre[x].lc;
if(tre[x].r==RR) si2=tre[x].rc;
if(L<=tre[x].l&&tre[x].r<=R) return tre[x].sum; if(tre[x].tag) push_down(x); int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) return query_sum(x<<,L,R);
if(L>mid) return query_sum(x<<|,L,R);
return query_sum(x<<,L,mid)+query_sum(x<<|,mid+,R)-(tre[x<<].rc==tre[x<<|].lc?:);
} void calc(int ss,int tt,int c){
int f1=top[ss],f2=top[tt];
while(f1!=f2){
if(dep[f1]<dep[f2]){ swap(f1,f2); swap(ss,tt); }
update(,id[f1],id[ss],c);
ss=fat[f1]; f1=top[ss];
}
if(dep[ss]<dep[tt]) swap(ss,tt);
update(,id[tt],id[ss],c);
} int calc(int ss,int tt){
int f1=top[ss],f2=top[tt],ans=;
int sid1=,sid2=;
while(f1!=f2){
if(dep[f1]<dep[f2]){ swap(f1,f2); swap(ss,tt); swap(sid1,sid2); }
LL=id[f1]; RR=id[ss];
ans+=query_sum(,id[f1],id[ss]);
if(si2==sid1) ans--;
sid1=si1; ss=fat[f1]; f1=top[ss];
}
if(dep[ss]<dep[tt]) { swap(ss,tt); swap(sid1,sid2); }
LL=id[tt]; RR=id[ss];
ans+=query_sum(,id[tt],id[ss]);
if(sid1==si2) ans--;
if(sid2==si1) ans--;
return ans;
} void solve(){
char opt;
int ss,tt,c;
for(int i=;i<m;i++){
opt=rea();
switch(opt){
case 'C':{
ss=read(); tt=read(); c=read();
calc(ss,tt,c);
break;
}
case 'Q':{
ss=read(); tt=read();
printf("%d\n",calc(ss,tt));
break;
}
}
}
} int main(){
//freopen("data.in","r",stdin);
init();
make();
solve();
return ;
}

それまでは 閉じこもって

あなたも卵の中なのね

[bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]的更多相关文章

  1. 2243: [SDOI2011]染色 树链剖分+线段树染色

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

  2. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

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

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

  4. B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

  5. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  6. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  7. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  8. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  9. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  10. bzoj 2157: 旅游【树链剖分+线段树】

    裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...

随机推荐

  1. MQL语句大全

    mysql sql语句大全 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql se ...

  2. VR全景,让VR不再是“空中楼阁“——智慧城市常诚

    VR的风口来了又走,而VR技术的支持者却始终在探索VR在各个领域的应用.最近,有业内专家表示,VR给带来的真正好处是,容易让人产生同理心,但同理心究竟能帮助我们做什么呢? 我第一次见到挪威建筑师Haa ...

  3. java中的中文参数存到数据库乱码问题

    关于java中的中文参数乱码问题,遇见过很多,若开发工具的字符集环境和数据库的字符集环境都一样,存到数据库中还是乱码的话,可以通过以下方法解决: 用数据库客户端检查每个字段的字符集和字符集校对和这个表 ...

  4. [转]如何使用BackTrack破解WIFI无线网络的WEP密钥

    aireplay-ng - -a (bssid) -h ::::: -e (essid) (interface) 你可能已经知道如果你想要加锁自己的WIFI无线网络,你最好选择WPA加密方式,因为WE ...

  5. CSDN删除上传资源的办法

    转自网友:http://blog.csdn.net/ssergsw/article/details/12489101 我按照下面的方法一试,果然成功了. 昨天晚上进行测试,上传了一个压缩包和大家分享, ...

  6. JVM高级特性-三、垃圾收集之判断对象存活算法

    一.概述 运行时数据区中,程序计数器.虚拟机栈.本地方法栈都是随线程而生随线程而灭的 因此,他们的内存分配和回收是确定的,在方法或线程结束时就回收.而Java堆和方 法区则是不确定的,程序运行过程中创 ...

  7. DDD理论学习系列(7)-- 值对象

    DDD理论学习系列--案例及目录 1.引言 提到值对象,我们可能立马就想到值类型和引用类型.而在C#中,值类型的代表是strut和enum,引用类型的代表是class.interface.delega ...

  8. ecshop邮件订阅按“订阅”没反应

    原订阅邮件所使用的JS文件transport.js和JQuery冲突,会更改transport.js文件,用以下代码可同样实现订阅功能. <input type="text" ...

  9. 一些java方面面试题,没事做做看看(带答案)

    1. Switch能否用string做参数? a.在?Java? <http://lib.csdn.net/base/java>7 之前, switch 只能支持byte,short,ch ...

  10. 小程序之发起请求 wx.request(object)的坑

    这是官方的API,然后官方的实例中 wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' , y: '' }, header: { ...