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 ...
随机推荐
- IntelliJ IDEA 12 与 Tomcat 集成并运行Web项目
配置Tomcat Server 1.Ctrl+Alt+s或者File——>Setting...;选中“Application Servers”点击"+" 创建运行配置 上面的 ...
- java 多线程——quartz 定时调度的例子
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- JavaScript实现冒泡排序、快速排序、插入排序
JavaScript实现冒泡排序.快速排序.插入排序 时间:2014-01-09 18:05:51 来源: 作者:胡晗 冒泡排序的基本思想:所谓冒泡就是泡泡一个一个往上冒,让体积最轻的泡泡浮在最上 ...
- js——<script>标签的加载顺序
用了很久的JavaScript,今天突然就碰见了将一个js文件放在<head></head>与<body></body>标签中,一个不可以执行,一个可以 ...
- PDF 补丁丁 0.4.1.728 测试版发布
书签编辑器新增预览界面,可查看书签所连接到文档的页数. 该功能将继续完善,请各位关注.
- 无需激活用户直接登入discuz
//打开discuz/api/uc.php //synlogin方法(180行)处,往下找到 if(($member = getuserbyuid($uid, 1))) { dsetcookie('a ...
- Centos 下搭建SVN + Apache 服务器(转载)
安装软件包 ? 1 # yum install httpd ? 1 # yum install mod_dav_svn ? 1 # yum install subversion 2. 验证安装 ? ...
- java日期的运用(DateUtils工具类)
public static void main(String[] args) { Date now = new Date(); SimpleDateFormat sd = new SimpleDate ...
- C# JObject解析Json(多方法解析Json 二)
下载Newtonsoft.Json,添加引用 记得using Newtonsoft.Json.Linq; //用JObject解析 string json = "{\"offlin ...
- struts中的常量,action配置中的默认值
1.struts中Action的开发方式 继承ActionSupport类,这种方法实现的Action可以进行数据校验: 实现Action接口: 不继承任何类,不实现任何接口: 是否继承类或实现接口, ...