HYSBZ - 2243 染色 (树链剖分+线段树)
题意:树上每个结点有自己的颜色,支持两种操作:1.将u到v路径上的点颜色修改为c; 2.求u到v路径上有多少段不同的颜色。
分析:树剖之后用线段树维护区间颜色段数。区间查询区间修改。线段树结点中维护的有:段数,左端点颜色,右端点颜色和懒惰标记。
当区间合并时,若左孩子的右端点颜色和右孩子的左端点颜色相同,那么段数要减1。
区间修改时注意维护左右端点的颜色。
查询时若左右子区间连接处的颜色相同,段数减1。
在两点向一条链上寻找LCA时,每次查询都要保存该条链顶端的颜色,若该链顶端的颜色与下次查询的右端点相同,那么段数减1。
最后当两点回溯到一条链上之后,若两点对应各自上次回溯链顶端的颜色是否与查询区间的左右端点相同,则答案都需减1。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define lson rt<<1
#define rson rt<<1|1
#define Lson l,m,lson
#define Rson m+1,r,rson
typedef long long LL;
using namespace std;
const int maxn =1e5+;
struct Edge{
int to,next;
}E[*maxn];
int n,head[maxn],tot;
int cnt,idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],id[maxn],rnk[maxn];
int a[maxn];
void init()
{
cnt=idx=tot=;
memset(head,-,sizeof(head));
dep[]=,fa[]=,size[]=;
memset(son,,sizeof(son));
} void AddEdge(int u,int v)
{
E[tot] = (Edge){v,head[u]};
head[u]=tot++;
}
void dfs1(int u)
{
size[u]=;
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
} void dfs2(int u,int topu)
{
top[u]= topu;
id[u] = ++idx;
rnk[idx] = u;
if(!son[u]) return;
dfs2(son[u],top[u]);
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
} struct Node{
int sum,add,lc,rc;
}tree[maxn<<];
int Lc,Rc;
void pushup(int rt){ //区间合并
tree[rt].sum = tree[lson].sum + tree[rson].sum;
tree[rt].lc = tree[lson].lc;
tree[rt].rc = tree[rson].rc;
if(tree[lson].rc==tree[rson].lc)
tree[rt].sum--;
}
void pushdown(int l,int r,int rt){
if(tree[rt].add){
tree[lson].add = tree[rson].add = ;
tree[lson].sum = tree[rson].sum = ;
tree[lson].lc = tree[lson].rc = tree[rt].lc;
tree[rson].lc = tree[rson].rc = tree[rt].lc;
tree[rt].add = ;
}
} void build(int l,int r,int rt)
{
tree[rt].add = ;
if(l==r){
tree[rt].sum = ;
tree[rt].lc = tree[rt].rc = a[rnk[l]];
return;
}
int m = (l+r)>>;
build(Lson);
build(Rson);
pushup(rt);
} void update(int L,int R,int col,int l=,int r=n,int rt=){
if(L<=l && R>=r){
tree[rt].sum = tree[rt].add =;
tree[rt].lc = tree[rt].rc = col;
return ;
}
pushdown(l,r,rt);
int m =(l+r)>>;
if(L<=m) update(L,R,col,Lson);
if(R>m) update(L,R,col,Rson);
pushup(rt);
} int query(int L,int R,int l=,int r=n,int rt=){ //单点
if(L==l) Lc = tree[rt].lc;
if(R==r) Rc = tree[rt].rc;
if(L<=l && R>=r)
return tree[rt].sum;
pushdown(l,r,rt);
int m = (l+r)>> , ans=; bool left = false;
if(L<=m) {
ans+=query(L,R,Lson);
left = true;
}
if(R>m){
ans +=query(L,R,Rson);
if(left && tree[lson].rc ==tree[rson].lc) ans--;
}
pushup(rt);
return ans;
} void CHANGE(int u,int v,int col)
{
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(id[top[u]],id[u],col);
u = fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
update(id[u],id[v],col);
} int Qsum(int u,int v)
{
int c1=-,c2=-, ans=; //记录上条链最左侧的颜色
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]){
swap(u,v);
swap(c1,c2);
}
ans +=query(id[top[u]],id[u]);
if(Rc == c1) ans--;
c1 = Lc;
u = fa[top[u]];
}
if(dep[u]>dep[v]){swap(u,v);swap(c1,c2);}
ans += query(id[u],id[v]);
if(Lc==c1) ans--;
if(Rc==c2) ans--;
return ans;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int m,q,u,v;
char op[];
while(scanf("%d%d",&n,&m)==){
init();
for(int i=;i<=n;++i) scanf("%d",&a[i]);
for(int i=;i<n;++i){
scanf("%d%d",&u,&v);
AddEdge(u,v);
AddEdge(v,u);
}
dfs1();
dfs2(,);
build(,n,);
while(m--){
scanf("%s",op);
if(op[]=='Q'){
scanf("%d%d",&u,&v);
printf("%d\n",Qsum(u,v));
}
else{
int col;
scanf("%d%d%d",&u,&v,&col);
CHANGE(u,v,col);
}
}
}
return ;
}
HYSBZ - 2243 染色 (树链剖分+线段树)的更多相关文章
- 2243: [SDOI2011]染色 树链剖分+线段树染色
给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- B20J_2243_[SDOI2011]染色_树链剖分+线段树
B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树
题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
随机推荐
- nested exception is java.lang.VerifyError: Expecting a stackmap frame at bra
Caused by: java.lang.VerifyError: Expecting a stackmap frame (2016-05-19 09:56:29) 转载▼ 标签: it 分类: Ja ...
- .NET学习笔记(1)
把 DataSet 绑定到 Repeater 控件 Repeater 控件用于显示重复的项目列表,这些项目被限制在该控件.Repeater 控件可被绑定到数据库表.XML 文件或者其他项目列表. 获取 ...
- python 的时间复杂度
Python内置方法的时间复杂度 本文翻译自Python Wiki 本文基于GPL v2协议,转载请保留此协议. 本页面涵盖了Python中若干方法的时间复杂度(或者叫“大欧”,“Big O”).该时 ...
- 讨论cocos2d-x字体绘制原理和应用方案
转自:http://blog.csdn.net/langresser_king/article/details/9012789 个人一直认为,文字绘制是cocos2d-x最薄弱的环节.对于愤怒的小鸟之 ...
- TCL V7300A-3D升级教程
鄙人的电视型号: 机器软件版本:V8-0MT-3201-LF1V028_000 3201是机芯 v028是版本号 设备型号:cn_mt32-v7300a-3d TCL电视升级有三个:本地.网络.自动 ...
- Html5-draggable元素拖动
Html5元素拖动 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. Internet Explorer 9+, Firefox, Opera, Chrome, 和 Safari 支持拖动 ...
- 回顾.NET Remoting分布式开发
记得在下第一次接触.NET Remoting分布式开发是在2003年,那时候是Framework1.0初次亮相之时,Remoting分布式开发是Framework1.0其中一个亮点.经过多年的发展,在 ...
- Python菜鸟之路:原生Ajax/Jquery Ajax/IFrame Ajax的选用
原生Ajax Jquery Ajax IFrame Ajax 如果发送的是普通的数据,比如用户简单的输入.选择的值,推荐使用Jquery ,其次用XMLHttpRquest对象,最次使用IFrame ...
- linux库冲突解决方法 apt purge / aptitude purge
remove libs: [apt-get purge remove] or [aptitude purge] how to use apt-get and aptitude https://blog ...
- python return中的or和and语句
python return中的or和and语句 1.二元运算: 如果一个True,一个False或两个false: return True and False # 返回False return Tru ...