P2486 [SDOI2011]染色
树链剖分
用区间修改线段树维护
对于颜色段的计算:sum[o]=sum[lc]+sum[rc]
因为可能重复计算,即左子树的右端点和右子树的左端点可能颜色相同
多开2个数组lx,rx记录左/右端点的颜色,重复的话 sum[o]- - 即可
(我的错误模板坑了我2h)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;}
template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;}
template <typename T> inline void read(T &x){
char c=getchar(); x=; bool f=;
while(!isdigit(c)) f= !f||c=='-' ? :,c=getchar();
while(isdigit(c)) x=(x<<)+(x<<)+(c^),c=getchar();
x= f ? x:-x;
}
template <typename T> inline void output(T x){
if(!x) {putchar(); return ;}
if(x<) putchar('-'),x=-x;
int wt[],l=;
while(x) wt[++l]=x%,x/=;
while(l) putchar(wt[l--]+);
}
typedef int arr[];
int n,m,cnt,tot;
arr d,fa,siz,bgs,tp,tmp,val,id,hd,ed;
int nxt[],poi[];
int lx[],rx[],sum[],tag[];
inline void add_(int x,int y){
nxt[ed[x]]=++cnt; hd[x]= hd[x] ? hd[x]:cnt;
ed[x]=cnt; poi[cnt]=y;
}
inline void pushdown(int o){
if(tag[o]==-) return ;
int lc=o<<,rc=o<<|;
sum[lc]=sum[rc]=;
lx[lc]=rx[lc]=lx[rc]=rx[rc]=tag[o];
tag[lc]=tag[rc]=tag[o];
tag[o]=-;
}
inline void maintain(int o){
int lc=o<<,rc=o<<|;
lx[o]=lx[lc],rx[o]=rx[rc],sum[o]=sum[lc]+sum[rc];
if(rx[lc]==lx[rc]) --sum[o]; //重复减掉
}
inline void build(int o,int l,int r){
tag[o]=-;
if(l==r) {tag[o]=lx[o]=rx[o]=tmp[l]; sum[o]=; return ;}
int lc=o<<,rc=o<<|,mid=l+((r-l)>>);
build(lc,l,mid); build(rc,mid+,r);
maintain(o);
}
inline void modify(int o,int l,int r,int x1,int x2,int v){
if(x1<=l&&r<=x2){
lx[o]=rx[o]=tag[o]=v; sum[o]=;
return ;
}pushdown(o);
int lc=o<<,rc=o<<|,mid=l+((r-l)>>);
if(x1<=mid) modify(lc,l,mid,x1,x2,v);
if(x2>mid) modify(rc,mid+,r,x1,x2,v);
maintain(o);
}
inline int query(int o,int l,int r,int x1,int x2){
if(x1<=l&&r<=x2) return sum[o];
pushdown(o); int res=;
int lc=o<<,rc=o<<|,mid=l+((r-l)>>);
if(x1<=mid) res+=query(lc,l,mid,x1,x2);
if(x2>mid){
res+=query(rc,mid+,r,x1,x2);
if(x1<=mid&&rx[lc]==lx[rc]) --res;
}return res;
}
inline void dfs1(int x,int _fa){
d[x]=d[_fa]+,fa[x]=_fa,siz[x]=;
for(int i=hd[x];i;i=nxt[i])
if(poi[i]!=_fa){
dfs1(poi[i],x);
siz[x]+=siz[poi[i]];
if(siz[bgs[x]]<siz[poi[i]]) bgs[x]=poi[i];
}
}
inline void dfs2(int x,int _top){
id[x]=++tot,tmp[tot]=val[x],tp[x]=_top;
if(siz[x]==) return;
dfs2(bgs[x],_top);
for(int i=hd[x];i;i=nxt[i])
if(poi[i]!=fa[x]&&poi[i]!=bgs[x])
dfs2(poi[i],poi[i]);
}
inline int findcol(int o,int l,int r,int x){
if(l==r) return tag[o];
pushdown(o);
int lc=o<<,rc=o<<|,mid=l+((r-l)>>);
if(x<=mid) return findcol(lc,l,mid,x);
else return findcol(rc,mid+,r,x);
}
inline void change(int x,int y,int v){
while(tp[x]!=tp[y]){ //™模板原来这里多套了个d数组上去,变成50pts
if(d[tp[x]]<d[tp[y]]) swap(x,y);
modify(,,n,id[tp[x]],id[x],v);
x=fa[tp[x]];
}if(d[x]>d[y]) swap(x,y);
modify(,,n,id[x],id[y],v);
}
inline int ask(int x,int y){
int res=,r1,r2;
while(tp[x]!=tp[y]){
if(d[tp[x]]<d[tp[y]]) swap(x,y);
res+=query(,,n,id[tp[x]],id[x]);
r1=findcol(,,n,id[tp[x]]);
r2=findcol(,,n,id[fa[tp[x]]]);
if(r1==r2) --res;
x=fa[tp[x]];
}if(d[x]>d[y]) swap(x,y);
res+=query(,,n,id[x],id[y]);
return max(res,);
}
int main(){
read(n); read(m); int q1,q2,q3; char opt[];
for(int i=;i<=n;++i) read(val[i]);
for(int i=;i<n;++i) read(q1),read(q2),add_(q1,q2),add_(q2,q1);
dfs1(,); dfs2(,); build(,,n);
for(int i=;i<=m;++i){
scanf("%s",opt); read(q1),read(q2);
if(opt[]=='Q') output(ask(q1,q2)),putchar('\n');
else read(q3),change(q1,q2,q3);
}return ;
}
P2486 [SDOI2011]染色的更多相关文章
- Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)
Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告
[SDOI2011]染色 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同 ...
- luogu P2486 [SDOI2011]染色
树剖做法: 就是两个dfs+一个线段树 难度的取决基本==线段树的维护难度 所以对有点线段树基础的,树剖也不难做吧 这里操作有二 一:两点间路径染色 线段树的区间赋值操作 二:查询路径段的个数 考虑线 ...
- P2486 [SDOI2011]染色(树剖)区间覆盖+区间的连续段
https://www.luogu.org/problemnew/show/P2486 值的一看https://www.cnblogs.com/Tony-Double-Sky/p/9283262.ht ...
- 洛谷 P2486 [SDOI2011]染色 LCT
Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...
- P2486 [SDOI2011]染色 维护区间块数 树链剖分
https://www.luogu.org/problemnew/show/P2486 题意 对一个树上维护两种操作,一种是把x到y间的点都染成c色,另一种是求x到y间的点有多少个颜色块,比如11 ...
- luogu题解P2486[SDOI2011]染色--树链剖分+trick
题目链接 https://www.luogu.org/problemnew/show/P2486 分析 看上去又是一道强行把序列上问题搬运到树上的裸题,然而分析之后发现并不然... 首先我们考虑如何在 ...
- 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...
随机推荐
- HTML/css之弹性布局
1.flex 弹性布局 产生的比较晚 目前在移动网页开发中可以使用 而且逐渐成为主流. 在桌面网页开发中,使用的比较少 (主要是桌面浏览器的兼容性问题更加严重) 开启方法: 在容器标签上,加上disp ...
- PPTP不使用远程网关访问公网设置
使用PPTP拨号的时候默认使用PPTP远程网关访问公网,通过以下设置可以禁止远程网关访问公网 1,右下角选择网络图标右键-属性 2,选择网络IPv4属性,选择属性 3,点击高级选项 4,在远程网络上使 ...
- 《机器学习实践》程序清单3-7 plotTree函数
这个plotTree函数,比较聪明,比较简化,比较抽象,作者一定是逐步优化和简化到这个程度的.我是花了小两天时间,断断续续看明白的,还是在参考了另一篇文章以后.这里是链接http://www.cnbl ...
- 使用 Python 进行 socket 编程
本文主要参考 https://docs.python.org/3/howto/sockets.html . 本文只讨论 STREAME(比如 TCP) INET(比如 IPv4) socket. 在多 ...
- Python面向对象:类、实例与访问限制
首先记录下面向对象的名词: 对象:python万物皆对象,程序设计的东西在对象上体现. 类:具有相同属性和行为的对象的集合. 消息:各个对象之间通过消息相互联系. 方法:对象功能实现的过程. 封装:把 ...
- 解决下载的CHM文件无法显示网页问题
问题症状:打开CHM文件,左边目录齐全,可右边边框里却是无法显示网页. 解决方法:方法一:修改注册表1)新建一个文本文件2)添加如下内容:REGEDIT4[HKEY_LOCAL_MACHINE\SOF ...
- SP11469 SUBSET-Balanced Cow Subsets meet-in-the-middle+状压
正解:折半搜索 解题报告: 传送门! 这题我开始看到的时候贼开心地就把这题的代码直接粘过来辣 然后就T辣,,,仔细思考一下,为什么呢? 因为会枚举到很多相同的状态 举个eg 20 1 1 1 1 1 ...
- form表单的enctype属性
①application/x-www-form-urlencoded : 数据被编码为名称/值对. ②multipart/form-data : 数据被编码为一条消息,页上的每个控件对应消息中的一个部 ...
- python string 模块
标准库 python3 python2.7 都可以用 sting.ascii_letters是生成所有字母,从a-z和A-Z, string.digits是生成所有数字0-9. import stri ...
- 帝国cms栏目别名怎样调用?栏目名称太短了
在用帝国cms创建栏目时一般会填写栏目名称(较短)和栏目别名(为空则与栏目名相同),栏目别名可以设置长一些作为栏目标题,可是如何调用帝国cms栏目别名呢?默认的模板标题调用是<title> ...