[SDOI2011] 染色(Luogu 2486)
题目描述

输入输出格式
输入格式:

输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
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
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)的更多相关文章
- [Luogu 2486] SDOI2011 染色
[Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...
- Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)
Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...
- [SDOI2011]染色(树链剖分)
[SDOI2011]染色(luogu) Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段 ...
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
- bzoj-2243 2243: [SDOI2011]染色(树链剖分)
题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6267 Solved: 2291 Descript ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- bzoj2243:[SDOI2011]染色
链剖就可以了.一开始的想法错了.但也非常接近了.妈呀调的要死...然后把字体再缩小一号查错起来比较容易QAQ. #include<cstdio> #include<cstring&g ...
- bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4637 Solved: 1726[Submit][Status ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
随机推荐
- POJ 2455 Secret Milking Machine(最大流+二分)
Description Farmer John is constructing a new milking machine and wishes to keep it secret as long a ...
- Sail
DescriptionThe polar bears are going fishing. They plan to sail from (sx,?sy) to (ex,?ey). However, ...
- “Hello world!”团队第二周贡献分规则+贡献分数分配结果
一.贡献规则制定: (1)基础分:9 , 9 , 8 , 7 , 7 , 7 , 6(按在本次编程中承担模块的重要度制定,某一模块重要度的认定通过组内开会讨论决定) (2)会议分:每人没出勤一次会议记 ...
- 第三周的psp
PSP: 进度条: 累计进度图: 本周PSP饼状图:
- 寒假学习计划——MOOC
课程 西安交通大学[https://www.icourse163.org/course/XJTU-46006?tid=1002265006] 理由 本身中国大学mooc里c++课程不多,完结了能够有很 ...
- MONyog-数据库性能监控工具
一.安装步骤 较为简单,网上可以搜索到,此处不做详细说明. 二.使用图解 此处介绍监控数据库连接量.并发量.吞吐量.响应时间等功能 1.设置连接需要监控的数据库 打开:http://127.0.0.1 ...
- 硬盘引导扇区、多分区图、不通硬盘的LINUX逻辑分区数量
主要启动记录区(Master Boot Record,MBR):可以安装开机管理程序的地方,有446byte 分割表(Paritition table):记录整块硬盘分割的状态,有64bytes 下面 ...
- php 生成短网址 代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- c++源文件到可执行文件的过程
1.预处理(preprocessor):对#pragma.#include.#define.#ifdef/#endif.#ifndef/#endif,inline内联函数等进行处理 2.编译(comp ...
- openstack之neutron
Neutron neutron主要就是用于网络虚拟化,之前将nova的时候说过,网络部分没有写,因为openstack中的网络属于一个大部分,所以今天咱们就来看看neutron到底是怎么样实现网络虚拟 ...