题目描述

输入输出格式

输入格式:

输出格式:

对于每个询问操作,输出一行答案。

输入输出样例

输入样例#1:

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
输出样例#1:

3
1
2

留一点自己思考的时间.

下面开始讲解.

题目大概题意是给出一颗树,树上每个节点都有一个颜色,让你求出一条路径上的颜色段数量,并需要对树进行修改.

看到树,很容易会想到是数据结构的题目.

需要对树上节点信息进行更新,并做到实时查询,这里采用了树链剖分.

树链剖分可以看我之前的讲解:树链剖分.

那么问题就转化成了记录一个区间的颜色段数量.如果用线段树来记录,那么可以直接存下一个节点的颜色段数量.但是当遇到区间的合并时,就需要判断两个合并的区间相连接的部分是否颜色一样. 如果一样,就将合并后两个区间颜色段数量相加再减一,否则直接相加.

但是当树剖部分中有一个跳链的步骤,从一条链跳到另一条链时就出现了两个区间需要合并的问题.为了解决这个问题,可以写一个函数对线段树中的端点的颜色进行单点查询.然后判断合并.

下面是代码:

#include<bits/stdc++.h>
#define mid (left+right>>1)
#define ll(x) (x<<1)
#define rr(x) (x<<1|1)
using namespace std;
const int inf=;
const int N=; int n,m,cn[N+];
int fa[N+],id[N+],son[N+],dep[N+],cs[N+],top[N+],size[N+],idx=;
int sum[N*+],lazy[N*+],lc[N*+],rc[N*+];
int cnt=,last[N+]; struct edge{
int to,next;
}e[N+]; int gi(){
int ans=,f=;char i=getchar();
while(i<''||i>''){if(i=='-')f=-;i=getchar();}
while(i>=''&&i<=''){ans=ans*+i-'';i=getchar();}
return ans*f;
} void add(int x,int y){
e[++cnt].to=y;
e[cnt].next=last[x];
last[x]=cnt;
} void dfs1(int x,int deep,int father){
dep[x]=deep; fa[x]=father; int maxson=-;
for(int i=last[x];i;i=e[i].next){
int to=e[i].to;
if(to!=father){
dfs1(to,deep+,x);
size[x]+=size[to];
if(maxson<size[to]){
son[x]=to;
maxson=size[to];
}
}
}
} void dfs2(int x,int tp){
top[x]=tp; id[x]=++idx; cs[idx]=cn[x];
if(!son[x]) return;
dfs2(son[x],tp);
for(int i=last[x];i;i=e[i].next){
int to=e[i].to;
if(to!=son[x]&&to!=fa[x])
dfs2(to,to);
}
} void pushdown(int root,int left,int right){
lazy[ll(root)]=lazy[rr(root)]=lazy[root];
lc[ll(root)]=lc[rr(root)]=lazy[root];
rc[ll(root)]=rc[rr(root)]=lazy[root];
sum[ll(root)]=sum[rr(root)]=;
lazy[root]=;
} void pushup(int root,int left,int right){
lc[root]=lc[ll(root)]; rc[root]=rc[rr(root)];
int res=sum[ll(root)]+sum[rr(root)];
if(rc[ll(root)]==lc[rr(root)]) res--;
sum[root]=res;
} void build(int root,int left,int right){
if(left==right){
lc[root]=rc[root]=cs[left];
//cout<<root<<' '<<cs[left]<<endl;;
sum[root]=;
return;
}
build(ll(root),left,mid);
build(rr(root),mid+,right);
pushup(root,left,right);
} void updata(int root,int left,int right,int l,int r,int col){
if(l<=left&&right<=r){
sum[root]=; lazy[root]=col;
lc[root]=rc[root]=col;
return;
}
if(lazy[root]) pushdown(root,left,right);
if(l<=mid) updata(ll(root),left,mid,l,r,col);
if(mid<r) updata(rr(root),mid+,right,l,r,col);
pushup(root,left,right);
} void cupdata(int a,int b,int val){
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]]) swap(a,b);
updata(,,n,id[top[a]],id[a],val);
a=fa[top[a]];
}
if(id[a]>id[b]) swap(a,b);
updata(,,n,id[a],id[b],val);
} int qcol(int root,int left,int right,int node){
if(left==right) return lc[root];
if(lazy[root]) pushdown(root,left,right);
if(node<=mid) return qcol(ll(root),left,mid,node);
else return qcol(rr(root),mid+,right,node);
} int query(int root,int left,int right,int l,int r){
if(l<=left&&right<=r) return sum[root];
if(r<left||right<l) return ;
if(lazy[root]) pushdown(root,left,right);
if(r<=mid) return query(ll(root),left,mid,l,r);
else if(mid<l) return query(rr(root),mid+,right,l,r);
else{
int res=query(ll(root),left,mid,l,r)+query(rr(root),mid+,right,l,r);
if(lc[rr(root)]==rc[ll(root)]) res--;
//cout<<res<<endl;
return res;
}
} int cquery(int a,int b){
int res=;
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]]) swap(a,b);
res+=query(,,n,id[top[a]],id[a]);
int LC=qcol(,,n,id[top[a]]),RC=qcol(,,n,id[fa[top[a]]]);
if(LC==RC) res--;
a=fa[top[a]];
}
if(id[a]>id[b]) swap(a,b);
res+=query(,,n,id[a],id[b]);
printf("%d\n",res);
} int main(){
n=gi(); m=gi(); int x , y , val ;char flag;
for(int i=;i<=n;i++) cn[i]=gi();
for(int i=;i<=n;i++) size[i]=;
for(int i=;i<n;i++){
x=gi(); y=gi();
add(x,y); add(y,x);
}
dfs1(,,-); dfs2(,); build(,,n);
//for(int i=1;i<=n;i++) cout<<i<<' '<<cs[i]<<endl;
for(int i=;i<=m;i++){
cin>>flag;
if(flag=='C'){
x=gi(); y=gi(); val=gi();
cupdata(x,y,val);
}
if(flag=='Q'){
x=gi(); y=gi();
cquery(x,y);
}
}
return ;
}

[SDOI2011] 染色(Luogu 2486)的更多相关文章

  1. [Luogu 2486] SDOI2011 染色

    [Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...

  2. Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)

    Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...

  3. [SDOI2011]染色(树链剖分)

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

  4. BZOJ 2243: [SDOI2011]染色 [树链剖分]

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

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

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

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

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

  7. bzoj2243:[SDOI2011]染色

    链剖就可以了.一开始的想法错了.但也非常接近了.妈呀调的要死...然后把字体再缩小一号查错起来比较容易QAQ. #include<cstdio> #include<cstring&g ...

  8. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

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

  9. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

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

随机推荐

  1. 【备忘】mysql常用操作汇总

    1.增删改查 // 插入一条数据 insert into tableName values('liu','bei') // 删除一条数据 delete from tableName where las ...

  2. eg_3

    3. 编写一个程序,返回一个 double 类型的二维数组,数组中的元素通过解析字符串参数获得,如字符串参数:“1,2;3,4,5;6,7,8”,则对应的数组为: d[0][0]=1.0, d[0][ ...

  3. 软工网络15个人作业4-alpha阶段个人总结(201521123059 叶文柠)

    一.个人总结 (1) 类别 具体技能和面试问题 现在回答 毕业找工作时 语言 最拿手的计算机语言之一,代码量多少? 感觉自己没有最拿手的语言,而且拿手的在计算机网络这方面的,所以在软件变成这方面的代码 ...

  4. (转)NEST.net Client For Elasticsearch简单应用

    由于最近的一个项目中的搜索部分要用到 Elasticsearch 来实现搜索功能,苦于英文差及该方面的系统性资料不好找,在实现时碰到了不少问题,现把整个处理过程的代码分享下,给同样摸索的人一些借鉴,同 ...

  5. C#Color颜色表

    Color.AliceBlue 240,248,255 Color.LightSalmon 255,160,122 Color.AntiqueWhite 250,235,215 Color.Light ...

  6. C++基础知识(二)

    八. 继承:让某个类的对象获得另一个类的对象的特性.通过继承可实现代码重用,即从已存在的类派生出的一个新类将自动具有原来那个类的特性. 类的继承还具有:(1)单向性:A类为B类的基类(父类),则派生类 ...

  7. BZOJ 2303 方格染色(带权并查集)

    要使得每个2*2的矩形有奇数个红色,如果我们把红色记为1,蓝色记为0,那么我们得到了这2*2的矩形里的数字异或和为1. 对于每个方格则有a(i,j)^a(i-1,j)^a(i,j-1)^a(i-1,j ...

  8. P1120 小木棍 [数据加强版](poj 1011)

    题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...

  9. [NOIP2017]宝藏 子集DP

    题面:[NOIP2017]宝藏 题面: 首先我们观察到,如果直接DP,因为每次转移的代价受上一个状态到底选了哪些边的影响,因此无法直接转移. 所以我们考虑分层DP,即每次强制现在加入的点的距离为k(可 ...

  10. BZOJ3224:普通平衡树——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3224 题面源于洛谷 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下 ...