P2486 [SDOI2011]染色 维护区间块数 树链剖分
题意
对一个树上维护两种操作,一种是把x到y间的点都染成c色,另一种是求x到y间的点有多少个颜色块,比如112221由“11”,“222”,“1”三块组成。
思路
这题的关键是要如何维护这个颜色块,我们可以利用线段树,记录每个区间的块数,区间左端点,区间右端点的颜色。合并中如果两个区间相邻点颜色相同,个数要减去1.
查询也是一样的,链与链间的相邻点也要考虑清楚。
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert> /* ⊂_ヽ
\\ Λ_Λ 来了老弟
\('ㅅ')
> ⌒ヽ
/ へ\
/ / \\
レ ノ ヽ_つ
/ /
/ /|
( (ヽ
| |、\
| 丿 \ ⌒)
| | ) /
'ノ ) Lノ */ using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n' #define boost ios::sync_with_stdio(false);cin.tie(0)
#define rep(a, b, c) for(int a = (b); a <= (c); ++ a)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c); const ll oo = 1ll<<;
const ll mos = 0x7FFFFFFF; //
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //
const ll mod = ;
const double esp = 1e-;
const double PI=acos(-1.0);
const double PHI=0.61803399; //黄金分割点
const double tPHI=0.38196601; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
} inline void cmax(int &x,int y){if(x<y)x=y;}
inline void cmax(ll &x,ll y){if(x<y)x=y;}
inline void cmin(int &x,int y){if(x>y)x=y;}
inline void cmin(ll &x,ll y){if(x>y)x=y;} /*-----------------------showtime----------------------*/ const int maxn = 1e5+;
int a[maxn],b[maxn];
int dp[maxn],sz[maxn],fa[maxn],son[maxn];
vector<int>mp[maxn]; void dfs1(int u,int f,int deep){
dp[u] = deep;
fa[u] = f;
sz[u] = ;
int mx = ;
for(int i=; i<mp[u].size(); i++){
int v = mp[u][i];
if(v == f) continue;
dfs1(v, u, deep+);
sz[u] += sz[v];
if(sz[v] > mx) {mx = sz[v], son[u] = v;}
}
} int top[maxn],id[maxn],cnt = ;
void dfs2(int u,int f,int topf){
top[u] = topf;
id[u] = ++cnt;
b[cnt] = a[u];
if(son[u])dfs2(son[u], u, topf);
for(int i=; i<mp[u].size(); i++){
int v = mp[u][i];
if(v == f || v == son[u]) continue;
dfs2(v, u, v);
}
} int tag[maxn<<],lazy[maxn<<],ly[maxn<<],rz[maxn<<];
void pushup(int rt){
tag[rt] = tag[rt<<] + tag[rt<<|];
rz[rt] = rz[rt<<];
ly[rt] = ly[rt<<|];
if(ly[rt<<] == rz[rt<<|])tag[rt] --;
}
void build(int l,int r,int rt){
if(l == r){
tag[rt] = ;
ly[rt] = rz[rt] = b[l];
return ;
}
int mid = (l + r) >> ;
build(l, mid, rt<<);
build(mid+,r,rt<<|);
pushup(rt);
// cout<<l<<" "<<r<<" "<<rz[rt] << " " << ly[rt]<<endl;
}
void pushdown(int l,int r,int rt){
tag[rt<<] = tag[rt<<|] = ;
ly[rt<<] = rz[rt<<] = lazy[rt];
ly[rt<<|] = rz[rt<<|] = lazy[rt];
lazy[rt<<] = lazy[rt<<|] = lazy[rt];
lazy[rt] = ;
}
void update(int L, int R, int c, int l, int r,int rt){
if(l >= L && r <= R){
tag[rt] = ;
ly[rt] = rz[rt] = c;
lazy[rt] = c;
return;
}
int mid = (l + r) >> ;
if(lazy[rt]) pushdown(l, r, rt);
if(mid >= L) update(L, R, c, l, mid, rt<<);
if(mid < R) update(L,R,c,mid+,r,rt<<|);
pushup(rt);
}
int n,m;
void solve(int x,int y,int c){
while(top[x] != top[y]){
if(dp[top[x]] < dp[top[y]]) swap(x, y);
update(id[top[x]], id[x], c, , n, );
x = fa[top[x]];
}
if(dp[x] > dp[y]) swap(x, y);
update(id[x], id[y], c, , n, );
} int query(int L,int R, int l,int r,int rt,int &tmpl,int &tmpr){
if(l >= L && r<= R){
if(l == L) tmpl = rz[rt];
if(r == R) tmpr = ly[rt]; return tag[rt];
}
int mid = (l + r) >> ;
if(lazy[rt])pushdown(l, r, rt);
int res = ;
int ql = -, qr = -;
if(mid >= L) {
res += query(L, R, l, mid, rt<<,tmpl,tmpr);
ql = ly[rt<<];
}
if(mid < R){
res += query(L, R, mid +, r, rt<<|,tmpl,tmpr);
qr = rz[rt<<|];
}
if(ql == qr && ql != -) res --;
pushup(rt);
return res;
}
int cal(int x,int y){
int res = ,lax = -,lay=-; while(top[x] != top[y]){
int tmpl = -,tmpr=-;
if(dp[top[x]] > dp[top[y]]) {
res += query(id[top[x]], id[x], , n, , tmpl, tmpr);//tmp,flag 1,r
if(lax == tmpr) res--;
lax = tmpl;
x = fa[top[x]];
}
else {
res += query(id[top[y]], id[y], , n, ,tmpl,tmpr);
if(lay == tmpr) res--;
lay = tmpl;
y = fa[top[y]];
} // cout<<tmpl<<" !! "<<tmpr<<endl;
} if(dp[x] > dp[y]){
int tmpl = -,tmpr=-;
res += query(id[y], id[x], , n, ,tmpl,tmpr);
if(tmpr == lax) res--;
if(tmpl == lay) res--;
}
else {
int tmpl = -,tmpr=-;
res += query(id[x], id[y], , n, ,tmpl,tmpr);
if(tmpl == lax) res--;
if(tmpr == lay) res--;
} return res;
}
int main(){
scanf("%d%d", &n, &m);
rep(i, , n) scanf("%d", &a[i]);
rep(i, , n-) {
int u,v;
scanf("%d%d", &u, &v);
mp[u].pb(v);
mp[v].pb(u);
}
dfs1(, , );
dfs2(, , );
build(, n, ); while(m--){
char str[];
scanf("%s", str);
if(str[] == 'C') {
int x,y,z;
scanf("%d%d%d", &x, &y, &z);
solve(x, y, z);
}
else {
int x,y;
scanf("%d%d", &x, &y);
printf("%d\n", cal (x,y));
} }
return ;
}
P2486 [SDOI2011]染色 维护区间块数 树链剖分的更多相关文章
- bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 7925 Solved: 2975[Submit][Status ...
- P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)
#include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...
- P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)
#include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...
- 2020牛客NOIP赛前集训营-提高组(第三场) C - 牛半仙的妹子Tree (树链剖分)
昨天教练问我:你用树剖做这道题,怎么全部清空状态呢? 我:???不是懒标记就完了??? 教练:树剖不是要建很多棵线段树吗,不止log个,你要一个一个清? 我:为什么要建很多棵线段树? ...
- luogu题解 P3950部落冲突--树链剖分
题目链接 https://www.luogu.org/problemnew/show/P3950 分析 大佬都用LCT,我太弱只会树链剖分 一个很裸的维护边权树链剖分题.按照套路,对于一条边\(< ...
- Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)
Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- bzoj 2243: [SDOI2011]染色 (树链剖分+线段树 区间合并)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9854 Solved: 3725[Submit][Status ...
- P2486 [SDOI2011]染色(树剖)区间覆盖+区间的连续段
https://www.luogu.org/problemnew/show/P2486 值的一看https://www.cnblogs.com/Tony-Double-Sky/p/9283262.ht ...
随机推荐
- WPF 动态添加按钮以及样式字典的引用(Style introduction)
我们想要达到的结果是,绑定多个Checkbox然后我们还可以获取它是否被选中,其实很简单,我们只要找到那几个关键的对象就可以了. 下面是Ui,其中定义了一个WrapPanel来存放CheckBox,还 ...
- 华为路由交换综合实验 ---IA阶段
目录 华为路由交换综合实验 ---IA阶段 实验拓扑 实验需求 华为路由交换综合实验 ---IA阶段 实验拓扑 实验需求 根据拓扑合理规划IP地址以及VLANIf地址(PC1属于运营部,PC2属于市场 ...
- 一文了解:Redis的RDB持久化
一文了解:Redis的RDB持久化 Redis是内存数据库,为了保证数据不在故障后丢失,Redis需要将数据持久化到硬盘上. Redis持久化有两种方式:一种是快照,全量备份.一种是AOF方式,连续增 ...
- Python学习系列:目录
Python学习系列(二)Python 编译原理简介 Python学习系列(三)Python 入门语法规则1 Python学习系列(四)Python 入门语法规则2
- Hadoop学习(9)-spark的安装与简单使用
spark和mapreduce差不多,都是一种计算引擎,spark相对于MapReduce来说,他的区别是,MapReduce会把计算结果放 在磁盘,spark把计算结果既放在磁盘中有放在内存中,ma ...
- python3学习-logging模块
1.logging模块的使用非常简单,引入模块就可以使用. import logging logging.debug('This is debug message') logging.info('Th ...
- SpringBoot学习系列之一(反射)
最近在学习SpringBoot的知识,动起手来学习的时候才发现SpringBoot项目采用了大量的反射机制,晕,作为一个应届毕业生,以前学习反射的时候给我的感觉就是,这个到底用来干嘛的,好像没啥用啊, ...
- alluxio源码解析-netty部分(2)
netty简介 Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. netty作为alluxio中重要的通讯组件 在常见的客户端上传,下载中,都会有n ...
- nginx在线与离线安装
1.场景描述 项目要部署到新的服务器上,需要安装nginx,刚好安全部门通知了nginx存在安全漏洞(Nginx整数溢出漏洞,nginx1.13.2之后的版本无问题),就下载最新的nginx进行了安装 ...
- C语言tips_1 关于&& || ! 的优先级
关于&& || ! 三种操作的优先级 测试如下 简要分析 假设&&>|| 则结果为1 假设||>&& 则结果为0 结果为1 得证 & ...