BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243)
题目大意
给定一颗树,每个节点上有一种颜色。
要求支持两种操作:
操作1:将a->b上所有点染成一种颜色。
操作2:询问a->b上的颜色段数量。
解题分析
树链剖分+线段树。
开一个记录类型,记录某一段区间的信息。l 表示区间最左侧的颜色 , r 表示区间最右侧的颜色 , sum 表示区间中颜色段数量。
合并时判断一下左区间的右端点和有区间的左端点的颜色是否一样。
树上合并时需要用两个变量ans1,ans2来存储。ans1表示x往上走时形成的链的信息,ans2表示y往上走时形成链的信息。
当x和y位于同一条重链上时,有三个区间需要合并在一起,注意判断顺序。
参考程序
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std; #define V 100008
#define E 200008
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 int n,m,cnt;
int a[V],size[V],dep[V],fa[V],son[V],top[V],w[V],rk[V]; struct line{
int u,v,nt;
}eg[E];
int sum,lt[V]; struct color{
int l,r,sum;
color(int a=-,int b=-,int c=-):l(a),r(b),sum(c){}
};
color merge(color a,color b){
color c;
if (a.sum==-) return b;
if (b.sum==-) return a;
if (a.r==b.l){
c.sum=a.sum+b.sum-;
c.l=a.l;
c.r=b.r;
}
else
{
c.sum=a.sum+b.sum;
c.l=a.l;
c.r=b.r;
}
return c;
} struct segment_tree{
color tag[V<<];
int lazy[V<<];
void pushup(int rt){
tag[rt]=merge(tag[rt<<],tag[rt<<|]);
}
void pushdown(int rt){
if (lazy[rt]){
lazy[rt<<]=lazy[rt<<|]=lazy[rt];
tag[rt<<].l=tag[rt<<].r=lazy[rt];
tag[rt<<|].l=tag[rt<<|].r=lazy[rt];
tag[rt<<].sum=tag[rt<<|].sum=;
lazy[rt]=;
return;
}
}
void build(int l,int r,int rt){
if (l==r){
tag[rt].l=tag[rt].r=a[rk[l]];
tag[rt].sum=;
return;
}
int m=(l+r)/;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,int val,int l,int r,int rt){
if (L<=l && r<=R){
tag[rt].l=tag[rt].r=val;
tag[rt].sum=;
lazy[rt]=val;
return;
}
pushdown(rt);
int m=(l+r)/;
if (L <= m) update(L,R,val,lson);
if (m < R) update(L,R,val,rson);
pushup(rt);
}
color query(int L,int R,int l,int r,int rt){
if (L<=l && r<=R){
return tag[rt];
}
pushdown(rt);
color res;
int m=(l+r)/;
if (L <= m) res=merge(res,query(L,R,lson));
if (m < R) res=merge(res,query(L,R,rson));
return res;
}
}T; void adt(int u,int v){
eg[++sum].u=u; eg[sum].v=v; eg[sum].nt=lt[u]; lt[u]=sum;
}
void add(int u,int v){
adt(u,v); adt(v,u);
} void dfs_1(int u){
size[u]=; dep[u]=dep[fa[u]]+; son[u]=;
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v==fa[u]) continue;
fa[v]=u;
dfs_1(v);
size[u]+=size[v];
if (size[v]>size[son[u]]) son[u]=v;
}
}
void dfs_2(int u,int tp){
w[u]=++cnt; top[u]=tp; rk[cnt]=u;
if (son[u]) dfs_2(son[u],tp);
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v==fa[u] || v==son[u]) continue;
dfs_2(v,v);
}
}
void change(int x,int y,int val){
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
T.update(w[top[x]],w[x],val,,n,);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
T.update(w[x],w[y],val,,n,);
}
void pt(color a){
printf("%d %d %d\n",a.l,a.r,a.sum);
}
void find(int x,int y){
color ans1,ans2,ans;
while (top[x]!=top[y]){
if (dep[top[x]]>dep[top[y]]){
ans1=merge(T.query(w[top[x]],w[x],,n,),ans1);
x=fa[top[x]];
}
else
{
ans2=merge(T.query(w[top[y]],w[y],,n,),ans2);
y=fa[top[y]];
} }
if (dep[x]<dep[y]){
ans=T.query(w[x],w[y],,n,);
ans=merge(ans,ans2);
swap(ans.l,ans.r);
ans=merge(ans,ans1);
}
else
{
ans=T.query(w[y],w[x],,n,);
ans=merge(ans,ans1);
swap(ans.l,ans.r);
ans=merge(ans,ans2);
}
printf("%d\n",ans.sum );
} int main(){
memset(lt,,sizeof(lt)); sum=; cnt=;
scanf("%d %d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<n;i++){
int u,v;
scanf("%d %d",&u,&v);
add(u,v);
}
dfs_1();
dfs_2(,);
T.build(,n,);
while (m--){
char ch[];
int x,y,z;
scanf("%s",ch);
if (ch[]=='Q'){
scanf("%d %d",&x,&y);
find(x,y);
}
else
{
scanf("%d %d %d",&x,&y,&z);
change(x,y,z);
};
}
}
BZOJ2243 (树链剖分+线段树)的更多相关文章
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- 【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 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- mouseover 和 hover 方法
mouseover 和 hover 方法的不同?jquery hover包括了鼠标移到对象上,同时鼠标再移出对象的过程,相应的子类也被选中. mouseover是鼠标经过对象时,不包含他的子类同时 ...
- #ifdef __cplusplus extern "C"
#ifdef __cplusplus extern "C" { #endif //一段代码 #ifdef __cplusplus } #endif首先,__cplusplus是cp ...
- JFrame面板
1.可见性与透明性 可见性:当面板不可见时,则该面板中包含的组件会无法显示. 透明性:若该面板是可见且透明的,那么只是面板会透明(比如面板的背景色无法看到),面板上的组件仍会显示. 注:可见性通过se ...
- 石子归并问题(nyoj737)
石子合并(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的 ...
- iOS App Icon图标 尺寸规范
Commit to AppStore:1024*1024 //for App IconIcon-60@3x.png:180*180 //iPhone 6 Plus (@3x)Icon-60@2x.pn ...
- 在Web中如何使用Windows控件(ActiveX)[转]
最近做的一个Web项目,需要在网页中播放摄像头采集的实时视频,我们已经有了播放视频的使用C#编写的windows控件,如何将其嵌入到网页中去了?这需要使用一种古老的技术,ActiveX. 1.将.Ne ...
- 复利计算4.0单元测试(c语言)
——————————复利计算程序单元测试报告—————————— ————————————4.0 单元测试—————————————— ————————————————要求—————————————— ...
- 四种java代码静态检查工具
[转载]常用 Java 静态代码分析工具的分析与比较 转载自 开源中国社区 http://www.oschina.net/question/129540_23043 1月16日厦门 OSC ...
- HDU 4906 Our happy ending(2014 Multi-University Training Contest 4)
题意:构造出n个数 这n个数取值范围0-L,这n个数中存在取一些数之和等于k,则这样称为一种方法.给定n,k,L,求方案数. 思路:装压 每位 第1为表示这种方案能不能构成1(1表示能0表示不能) ...
- 设置groupBox背景透明
步骤:属性-BackColor-WEB面板-Transparent