[bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
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]之间。
My Solution
一道可爱的树链剖分题啊
注意区间合并和树剖中的calc即可
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; inline int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} inline char rea(){
char ch;
while((ch=getchar())!='Q'&&ch!='C');
return ch;
} struct edge{
int to,next;
edge(int to=,int next=):
to(to),next(next){}
}; struct segment{
int l,r,lc,rc,sum,tag;
}; const int maxn=1e5+; edge edges[maxn<<];
segment tre[maxn<<];
int n,m,cnt=,root;
//si1,si2表示query操作中取到的最高和最低颜色
int si1,si2,LL,RR;
int head[maxn],data[maxn];
int siz[maxn],fat[maxn],son[maxn],dep[maxn],id[maxn],id_[maxn],top[maxn]; inline void add_edge(int from,int to){
edges[++cnt]=edge(to,head[from]); head[from]=cnt;
edges[++cnt]=edge(from,head[to]); head[to]=cnt;
} void init(){
n=read(); m=read();
for(int i=;i<=n;i++) data[i]=read();
int from,to; cnt=;
for(int i=;i<n;i++){
from=read(); to=read();
add_edge(from,to);
}
} void dfs_1(int x,int fa){
siz[x]=;
dep[x]=dep[fa]+;
fat[x]=fa;
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fa){
dfs_1(edges[ee].to,x);
siz[x]+=siz[edges[ee].to];
if(!son[x]||siz[edges[ee].to]>siz[son[x]]) son[x]=edges[ee].to;
}
} void dfs_2(int x,int first){
top[x]=first;
id[x]=++cnt;
id_[cnt]=x;
if(!son[x]) return;
dfs_2(son[x],first);
for(int ee=head[x];ee;ee=edges[ee].next)
if(edges[ee].to!=fat[x]&&edges[ee].to!=son[x]) dfs_2(edges[ee].to,edges[ee].to);
} void push_up(int x){
int lson=x<<,rson=lson|;
tre[x].lc=tre[lson].lc;
tre[x].rc=tre[rson].rc;
tre[x].sum=tre[lson].sum+tre[rson].sum-(tre[lson].rc==tre[rson].lc?:);
} void build(int x,int l,int r){
tre[x].l=l; tre[x].r=r;
if(l==r){
tre[x].lc=tre[x].rc=data[id_[l]];
tre[x].sum=;
return;
}
int mid=(l+r)>>;
build(x<<,l,mid); build(x<<|,mid+,r);
push_up(x);
} void push_down(int x){
int lson=x<<,rson=lson|;
int &c=tre[x].tag;
tre[lson].tag=tre[rson].tag=tre[lson].lc=
tre[lson].rc=tre[rson].lc=tre[rson].rc=c;
tre[lson].sum=; tre[rson].sum=;
c=;
} void make(){
root=; dfs_1(root,);
cnt=; dfs_2(root,root);
build(,,n);
} void update(int x,int L,int R,int c){
if(L<=tre[x].l&&tre[x].r<=R){
tre[x].lc=tre[x].rc=tre[x].tag=c;
tre[x].sum=;
return;
} if(tre[x].tag) push_down(x); int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) update(x<<,L,R,c);
else if(L>mid) update(x<<|,L,R,c);
else{
update(x<<,L,mid,c);
update(x<<|,mid+,R,c);
}
push_up(x);
} int query_sum(int x,int L,int R){
if(tre[x].l==LL) si1=tre[x].lc;
if(tre[x].r==RR) si2=tre[x].rc;
if(L<=tre[x].l&&tre[x].r<=R) return tre[x].sum; if(tre[x].tag) push_down(x); int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) return query_sum(x<<,L,R);
if(L>mid) return query_sum(x<<|,L,R);
return query_sum(x<<,L,mid)+query_sum(x<<|,mid+,R)-(tre[x<<].rc==tre[x<<|].lc?:);
} void calc(int ss,int tt,int c){
int f1=top[ss],f2=top[tt];
while(f1!=f2){
if(dep[f1]<dep[f2]){ swap(f1,f2); swap(ss,tt); }
update(,id[f1],id[ss],c);
ss=fat[f1]; f1=top[ss];
}
if(dep[ss]<dep[tt]) swap(ss,tt);
update(,id[tt],id[ss],c);
} int calc(int ss,int tt){
int f1=top[ss],f2=top[tt],ans=;
int sid1=,sid2=;
while(f1!=f2){
if(dep[f1]<dep[f2]){ swap(f1,f2); swap(ss,tt); swap(sid1,sid2); }
LL=id[f1]; RR=id[ss];
ans+=query_sum(,id[f1],id[ss]);
if(si2==sid1) ans--;
sid1=si1; ss=fat[f1]; f1=top[ss];
}
if(dep[ss]<dep[tt]) { swap(ss,tt); swap(sid1,sid2); }
LL=id[tt]; RR=id[ss];
ans+=query_sum(,id[tt],id[ss]);
if(sid1==si2) ans--;
if(sid2==si1) ans--;
return ans;
} void solve(){
char opt;
int ss,tt,c;
for(int i=;i<m;i++){
opt=rea();
switch(opt){
case 'C':{
ss=read(); tt=read(); c=read();
calc(ss,tt,c);
break;
}
case 'Q':{
ss=read(); tt=read();
printf("%d\n",calc(ss,tt));
break;
}
}
}
} int main(){
//freopen("data.in","r",stdin);
init();
make();
solve();
return ;
}
それまでは 閉じこもって
あなたも卵の中なのね
[bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]的更多相关文章
- 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$代表该区间的所有连续颜 ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
随机推荐
- mybatis在mysql和oracle批量插入不同
两者不同 1,批量插入 2,主键自增 3,分页不同 4,......待补充 批量插入 mysql: <insert id="batchinsertSelective" par ...
- Nodejs-express 4.0框架 简单介绍
http://www.expressjs.com.cn/4x/api.html 这个是express API的中文手册 但是只是翻译了一点 英语比较差比较难受. 1. 关于安装 现在网上查的时候有一 ...
- Asp.Net生命周期的详解
一.Asp.Net页面生命周期的概念 当我们在浏览器地址栏中输入网址,回车查看页面时,这时会向服务器端IIS)发送一个request请求,服务器就会判断发送过来的请求页面,当完全识别 TTP页面处理程 ...
- 如何用phpcms将静态网页生成动态网页?
在前两篇随笔中已经简单介绍了phpcms,那么现在让我们来看一下如何用phpcms将静态网页生成动态网页? 1.在templates文件夹下新建模板文件夹ceshi(名字可以自己随笔起) 2.在ces ...
- django ngRoute ui-router 开发环境下禁用缓存
问题描述: Python manage.py runserver ,禁用缓存,及时修改反馈到浏览器 解决办法: 使用dummy cache: Dummy caching (for developmen ...
- ubuntu忽然不能登录,输入密码正确一直返回登录界面
问题描述 由于配置eclipse命令启动,我修改了 /etc/environment 文件的内容,用命令 shutdown -r -now 重启后,输入密码正确一直返回登录界面. 查了下网上资料:系统 ...
- Owl Carousel幻灯片插件的使用
Owl Carousel 是一个强大.实用但小巧的 jQuery 幻灯片插件,它具有一下特点: 兼容所有浏览器 支持响应式 支持 CSS3 过度 支持触摸事件 支持 JSON 及自定义 JSON 格式 ...
- 【LCA求最近公共祖先+vector构图】Distance Queries
Distance Queries 时间限制: 1 Sec 内存限制: 128 MB 题目描述 约翰的奶牛们拒绝跑他的马拉松,因为她们悠闲的生活不能承受他选择的长长的赛道.因此他决心找一条更合理的赛道 ...
- Oracle数据库ora-01722 错误小记
今天遇到个关联查询的错误,特搜索了下记录下来. 因为做视图查询的表是以前建立的,所以有个字段类型应该只实用于当时.看SQL: select x.参数1 , y.参数2 from t_fac_info ...
- 【RAC】RAC相关基础知识
[RAC]RAC相关基础知识 1.CRS简介 从Oracle 10G开始,oracle引进一套完整的集群管理解决方案—-Cluster-Ready Services,它包括集群连通性.消息和锁. ...