BZOJ2243:[SDOI2011]染色——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2243
Description
Input
Output
对于每个询问操作,输出一行答案。
Sample Input
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
Sample Output
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
————————————————————————————————
(吐槽一下BZOJ,洛谷能过的代码BZOJ RE……后来优化了读入才AC……坑爹啊)
首先是树链剖分的裸题。点这里看树链剖分原理。
然后考虑合并区间时候的问题。
我们记录每个区间的端点颜色,区间个数,当然还有lazy标记。
然后区间合并看相邻的端点颜色是否一致,如果一致答案就-1。
树上需要特意查重路径的顶点和他爸颜色是否一致,如果一致答案就-1。
#include<cstdio>
#include<iostream>
using namespace std;
const int N=;
int read(){
int X=,w=;char ch=;
while(ch<''||ch>''){w|=ch=='-';ch=getchar();}
while(ch>=''&&ch<='')X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int to;
int nxt;
}edge[*N];
struct tree{
int lc;
int rc;
int num;
int lazy;
}t[*N];
int head[N],cnt=,n;
void add(int u,int v){
cnt++;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
return;
}
int fa[N],dep[N],size[N],son[N],top[N],pos[N],idx[N];
int val[N];
void dfs1(int u){
size[u]=;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u])continue;
fa[v]=u;dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if(!son[u]||size[v]>size[son[u]])son[u]=v;
}
return;
}
int tot;
void dfs2(int u,int anc){
tot++;
pos[u]=tot;
idx[tot]=u;
top[u]=anc;
if(!son[u])return;
dfs2(son[u],anc);
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
return;
}
void init(){
dfs1();
top[]=idx[]=pos[]=;
tot=;
dfs2(,);
return;
}
void pushdown(int a){
if(t[a].lazy!=-){
t[a*].lazy=t[a*+].lazy=t[a].lazy;
t[a*].lc=t[a*].rc=t[a].lazy;
t[a*+].lc=t[a*+].rc=t[a].lazy;
t[a*].num=t[a*+].num=;
t[a].lazy=-;
}
return;
}
void build(int a,int l,int r){
t[a].lazy=-;
if(l==r){
t[a].lc=val[idx[l]];
t[a].rc=val[idx[l]];
t[a].num=;
return;
}
int mid=(l+r)>>;
build(a*,l,mid);
build(a*+,mid+,r);
t[a].lc=t[a*].lc;t[a].rc=t[a*+].rc;
t[a].num=t[a*].num+t[a*+].num;
if(t[a*].rc==t[a*+].lc)t[a].num--;
return;
}
int query(int a,int l,int r,int l1,int r1){
if(r1<l||l1>r)return ;
if(l1<=l&&r<=r1){
return t[a].num;
}
int mid=(l+r)>>;
pushdown(a);
int k1=query(a*,l,mid,l1,r1);
int k2=query(a*+,mid+,r,l1,r1);
if(k1&&k2){
if(t[a*].rc==t[a*+].lc)k1--;
}
return k1+k2;
}
int check(int a,int l,int r,int k){
if(l==r)return t[a].lc;
int mid=(l+r)>>;
pushdown(a);
if(l<=k&&k<=mid)return check(a*,l,mid,k);
else if(mid<k&&k<=r)return check(a*+,mid+,r,k);
}
int pathquery(int u,int v){
int res=;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]){int t=u;u=v;v=t;}
int ans=query(,,n,pos[top[u]],pos[u]);
if(check(,,n,pos[top[u]])==check(,,n,pos[fa[top[u]]]))ans--;
res+=ans;
u=fa[top[u]];
}
if(dep[u]>dep[v]){int t=u;u=v;v=t;}
return res+query(,,n,pos[u],pos[v]);
}
void modify(int a,int l,int r,int l1,int r1,int v){
if(r1<l||r<l1)return;
if(l1<=l&&r<=r1){
t[a].lazy=v;
t[a].lc=v;t[a].rc=v;
t[a].num=;
return;
}
int mid=(l+r)>>;
pushdown(a);
modify(a*,l,mid,l1,r1,v);
modify(a*+,mid+,r,l1,r1,v);
t[a].lc=t[a*].lc;t[a].rc=t[a*+].rc;
t[a].num=t[a*].num+t[a*+].num;
if(t[a*].rc==t[a*+].lc)t[a].num--;
return;
}
void pathmodify(int u,int v,int c){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]){int t=u;u=v;v=t;}
modify(,,n,pos[top[u]],pos[u],c);
u=fa[top[u]];
}
if(dep[u]>dep[v]){int t=u;u=v;v=t;}
modify(,,n,pos[u],pos[v],c);
return;
}
int main(){
n=read();int q=read();
for(int i=;i<=n;i++)val[i]=read();
for(int i=;i<=n;i++){
int u=read();
int v=read();
add(u,v);
add(v,u);
}
init();
build(,,n);
while(q--){
char op=;
while(op!='C'&&op!='Q')op=getchar();
if(op=='C'){
int a=read();
int b=read();
int c=read();
pathmodify(a,b,c);
}else{
int a=read();
int b=read();
printf("%d\n",pathquery(a,b));
}
}
return ;
}
BZOJ2243:[SDOI2011]染色——题解的更多相关文章
- BZOJ2243 SDOI2011 染色 【树链剖分】
BZOJ2243 SDOI2011 染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- [bzoj2243][SDOI2011]染色
Description 给定一棵有$n$个节点的无根树和$m$个操作,操作有$2$类: 1.将节点$a$到节点$b$路径上所有点都染成颜色$c$; 2.询问节点$a$到节点$b$路径上的颜色段数量(连 ...
- BZOJ2243[SDOI2011]染色——树链剖分+线段树
题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221 ...
- [BZOJ2243][SDOI2011]染色 解题报告|树链剖分
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- BZOJ2243: [SDOI2011]染色(树链剖分/LCT)
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...
- bzoj2243: [SDOI2011]染色--线段树+树链剖分
此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...
- BZOJ2243——[SDOI2011]染色
1.题目大意:给个树,然后树上每个点都有颜色,然后会有路径的修改,有个询问,询问一条路径上的颜色分成了几段 2.分析:首先这个修改是树剖可以做的,对吧,但是这个分成了几段怎么搞呢,我们的树剖的不是要建 ...
随机推荐
- NavRouter
使用方法只需要跟vue-router一样正常使用即可,这里我们新加了一个路由跳转方法nav: router.nav()//参数同router.replace一样. 路由跳转策略 首先说下路由跳转过程, ...
- 「日常训练」Watering Flowers(Codeforces Round #340 Div.2 C)
题意与分析 (CodeForces 617C) 题意是这样的:一个花圃中有若干花和两个喷泉,你可以调节水的压力使得两个喷泉各自分别以\(r_1\)和\(r_2\)为最远距离向外喷水.你需要调整\(r_ ...
- 第四十篇 Python之设计模式总结-简单工厂、工厂方法、抽象工厂、单例模式
一. 简单工厂 简单工厂模式(Simple Factory Pattern):是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 简单工厂的用处不大,主要就是一个if... ...
- Linux命令应用大词典-第44章 PPPoE配置
44.1 pppoe-setup:配置PPPoE客户端 44.2 ppoe-connect:管理PPPoE链路 44.3 pppoe-start:启动PPPoE链路 44.4 pppoe-stop:关 ...
- 【rich-text】 富文本组件说明
[rich-text] 富文本组件可以显示HTML代码样式. 1)支持事件:tap.touchstart.touchmove.touchcancel.touchend和longtap 2)信任的HTM ...
- List和String数组相互转化
在工作中经常会遇到需要String[] 参数的地方,我们可以先定义一个list,再转成String[] 来使用,使用list的好处自然是可以随时方便的添加删除元素,下面是方法: List list = ...
- linux学习总结----redis总结
安装 下载:打开redis官方网站,推荐下载稳定版本(stable) 解压 tar zxvf redis-3.2.5.tar.gz 复制:推荐放到usr/local目录下 sudo mv -r ...
- 《Spark 官方文档》在Mesos上运行Spark
本文转自:http://ifeve.com/spark-mesos-spark/ 在Mesos上运行Spark Spark可以在由Apache Mesos 管理的硬件集群中运行. 在Mesos集群中使 ...
- 人脸识别 ArcFace Demo [Windows]
Arcsoft ArcfaceDemo for Windows, VS2013 C++ 使用虹软技术开发完成 使用步骤: 1.下载SDK包,32位Windows平台将五个SDK包里lib中的文件到 ...
- numpy切片和布尔型索引
numpy 标签(空格分隔): numpy 数据挖掘 切片 数组切片是原始数组的视图.这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上 In [16]: arr Out[16]: arr ...