【Luogu】P2486染色(树链剖分)
线段树维护左端颜色,右端颜色,颜色段数量。
合并的时候看左子树的右端颜色是不是等于右子树的左端颜色,如果等于那么颜色段数量要-1S
然后在树剖跳链的时候搞同样的操作qwq
然后就没有然后了
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cstdlib>
#define maxn 500000
#define left (rt<<1)
#define right (rt<<1|1)
#define mid ((l+r)>>1)
#define lson l,mid,left
#define rson mid+1,r,right
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} int n,m;
int tag[maxn*];
int deep[maxn];
int dfn[maxn],ID;
int back[maxn];
int q[maxn];
int son[maxn];
int top[maxn];
int father[maxn];
int size[maxn]; struct Edge{
int next,to;
}edge[maxn*];
int head[maxn],num;
inline void add(int from,int to){
edge[++num]=(Edge){head[from],to};
head[from]=num;
} struct Node{
int lcol,rcol,ncol;
Node operator +(const Node a){
Node ans=(Node){lcol,a.rcol,ncol+a.ncol};
if(rcol==a.lcol) ans.ncol--;
return ans;
}
}tree[maxn*]; inline void pushup(int rt){
tree[rt]=tree[left]+tree[right];
} inline void pushdown(int rt){
if(tag[rt]==) return;
tag[left]=tag[right]=tag[rt];
tree[left].lcol=tree[right].lcol=tree[left].rcol=tree[right].rcol=tag[rt];
tree[left].ncol=tree[right].ncol=;
tag[rt]=;
} void build(int l,int r,int rt){
if(l==r){
int last=back[l];
tree[rt]=(Node){q[last],q[last],};
return;
}
build(lson);
build(rson);
pushup(rt);
} void update(int from,int to,int num,int l,int r,int rt){
if(from<=l&&to>=r){
tree[rt]=(Node){num,num,};
tag[rt]=num;
return;
}
pushdown(rt);
if(from<=mid) update(from,to,num,lson);
if(to>mid) update(from,to,num,rson);
pushup(rt);
return;
} int query(int from,int to,int l,int r,int rt){
if(from<=l&&to>=r) return tree[rt].ncol;
pushdown(rt);
int ans=;
if(from<=mid) ans+=query(from,to,lson);
if(to>mid) ans+=query(from,to,rson);
if(from<=mid&&to>mid)
if(tree[left].rcol==tree[right].lcol) ans--;
return ans;
} int qucol(int o,int l,int r,int rt){
if(l==r) return tree[rt].lcol;
pushdown(rt);
if(o<=mid) return qucol(o,lson);
else return qucol(o,rson);
} void findfs(int x,int fa){
deep[x]=deep[fa]+; size[x]=; father[x]=fa;
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==fa) continue;
findfs(to,x);
size[x]+=size[to];
if(son[x]==||size[son[x]]<size[to]) son[x]=to;
}
} void unidfs(int x,int Top){
top[x]=Top;
dfn[x]=++ID; back[ID]=x;
if(son[x]==) return;
unidfs(son[x],Top);
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==father[x]||to==son[x]) continue;
unidfs(to,to);
}
} void uplink(int from,int to,int num){
while(top[from]!=top[to]){
if(deep[top[from]]<deep[top[to]]) swap(from,to);
update(dfn[top[from]],dfn[from],num,,n,);
from=father[top[from]];
}
if(deep[from]>deep[to]) swap(from,to);
update(dfn[from],dfn[to],num,,n,);
} int qulink(int from,int to){
int ans=;
while(top[from]!=top[to]){
if(deep[top[from]]<deep[top[to]]) swap(from,to);
ans+=query(dfn[top[from]],dfn[from],,n,);
from=top[from];
if(qucol(dfn[from],,n,)==qucol(dfn[father[from]],,n,)) ans--;
from=father[from];
}
if(deep[from]>deep[to]) swap(from,to);
ans+=query(dfn[from],dfn[to],,n,);
return ans;
} int main(){
n=read(),m=read();
for(int i=;i<=n;++i) q[i]=read();
for(int i=;i<n;++i){
int from=read(),to=read();
add(from,to);
add(to,from);
}
findfs(,);
unidfs(,);
build(,n,);
for(int i=;i<=m;++i){
char ch[]; int a,b;
scanf("%s%d%d",ch,&a,&b);
if(ch[]=='Q') printf("%d\n",qulink(a,b));
else if(ch[]=='C'){
int c=read();
uplink(a,b,c);
}
}
return ;
}
【Luogu】P2486染色(树链剖分)的更多相关文章
- [luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)
Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...
- luogu题解P2486[SDOI2011]染色--树链剖分+trick
题目链接 https://www.luogu.org/problemnew/show/P2486 分析 看上去又是一道强行把序列上问题搬运到树上的裸题,然而分析之后发现并不然... 首先我们考虑如何在 ...
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
- bzoj-2243 2243: [SDOI2011]染色(树链剖分)
题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6267 Solved: 2291 Descript ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- [bzoj 2243]: [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 ...
随机推荐
- 后台登录验证(Tokens/JSON Web Tokens(JWT) 的认证机制)
sessionid不支持跨域,浏览器也不能禁止cookie(禁止以后sessionid还有什么用) 单点登录问题,即时SessionID一样,也无法跨域获取到数据 占坑
- [dp]uestc oj 邱老师看电影
定义状态dp[w][b]表示有w只白老鼠,b只黑老鼠时妹子赢的概率,分两种情况妹子抓到白老鼠概率为w/(w+b)和否则只有妹子抓黑老鼠和邱老师抓黑老鼠妹子才可能赢,再分两种情况:酱神抓白老鼠,状态 ...
- 使用Python-OpenCV向图片添加噪声(高斯噪声、椒盐噪声)
在matlab中,存在执行直接得函数来添加高斯噪声和椒盐噪声.Python-OpenCV中虽然不存在直接得函数,但是很容易使用相关的函数来实现. 代码: import numpy as np impo ...
- hd - MFM/IDE 硬盘设备
描述 DESCRIPTION hd* 开头的设备是以裸模式(raw mode)访问MFM/IDE类型硬盘的块设备. 第一个IDE驱动控制器上的主盘(主设备号3)是 hda ;从盘是 hdb. 第二个I ...
- 第011课_串口(UART)的使用
from: 第011课_串口(UART)的使用 第001节_辅线1_硬件知识_UART硬件介绍 1. 串口的硬件介绍 UART的全称是 Universal Asynchronous Receiver ...
- Mysql 8.0 新特性
转载:https://www.jianshu.com/p/be29467c2b0c
- [].indexOf.call()学习
今天看到闭包一道题,就是一个li列表,点击列表控制台输出对应的索引.这里考察了var的作用域问题和闭包对外部变量的引用问题,有几种解决方法. html: <ul> <li>te ...
- numpy中常用的函数
1. power(x1, x2) 对x1中的每个元素求n次方.不会改变x1上午shape. 2. sum(a, axis=None, dtype=None, out=None, keepdims=Fa ...
- 如何使用jmeter做关联
1.适用场景 从上一个接口的返回值中获取值传递给下一个接口使用 2.添加JSON Extractor 在需求提取的参数上添加--后置处理器--JSON Extractor 从登录接口的返回值中取use ...
- Library setup