题意

对一个树上维护两种操作,一种是把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]染色 维护区间块数 树链剖分的更多相关文章

  1. bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 7925  Solved: 2975[Submit][Status ...

  2. P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)

    #include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...

  3. P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)

    #include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...

  4. 2020牛客NOIP赛前集训营-提高组(第三场) C - 牛半仙的妹子Tree (树链剖分)

    昨天教练问我:你用树剖做这道题,怎么全部清空状态呢?    我:???不是懒标记就完了???    教练:树剖不是要建很多棵线段树吗,不止log个,你要一个一个清?    我:为什么要建很多棵线段树? ...

  5. luogu题解 P3950部落冲突--树链剖分

    题目链接 https://www.luogu.org/problemnew/show/P3950 分析 大佬都用LCT,我太弱只会树链剖分 一个很裸的维护边权树链剖分题.按照套路,对于一条边\(< ...

  6. Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)

    Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...

  7. 洛谷 P2486 [SDOI2011]染色 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...

  8. bzoj 2243: [SDOI2011]染色 (树链剖分+线段树 区间合并)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9854  Solved: 3725[Submit][Status ...

  9. P2486 [SDOI2011]染色(树剖)区间覆盖+区间的连续段

    https://www.luogu.org/problemnew/show/P2486 值的一看https://www.cnblogs.com/Tony-Double-Sky/p/9283262.ht ...

随机推荐

  1. jmeter Linux环境执行总报错 cannot allocate memory

    1.windows环境写好的测试用例,执行没有问题,在Linux环境跑总是报错,提示如下 cannot allocate memory 2.一开始以为是哪块设置有问题,因为脚本里边有设置邮件自动发送, ...

  2. 【Spring】No converter found for return value of type: class java.util.ArrayList

    错误信息: org.springframework.http.converter.HttpMessageNotWritableException: No converter found for ret ...

  3. Handler 使用详解

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  4. Selenium+java - Ajax浮动框处理

    Ajax浮动框 我们常遇到的某些网站首页输入框,点击后显示的浮动下拉热点,如下图: 实际案例 模拟场景如下: hao123首页搜索输入框,单击搜索框,点击浮动框中的哪吒票房破30亿,单击后选项的文字内 ...

  5. 原 CNN--卷积神经网络从R-CNN到Faster R-CNN的理解(CIFAR10分类代码)

    1. 什么是CNN 卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Netwo ...

  6. hadoop的基础思想

    转载 http://www.superwu.cn/2014/01/10/963 1.1.1. hadoop的核心思想 Hadoop包括两大核心,分布式存储系统和分布式计算系统.1.1.1.1. 分布式 ...

  7. 基于RBAC的权限框架

    RBAC权限框架(Role-Based Access Control)基于角色的权限访问控制的框架,通过用户-角色-权限的关联,非常方便的进行权限管理,在这里不再说明什么是RBAC,请自行百度. 谢谢 ...

  8. Tomcat源码分析 (五)----- Tomcat 类加载器

    在研究tomcat 类加载之前,我们复习一下或者说巩固一下java 默认的类加载器.楼主以前对类加载也是懵懵懂懂,借此机会,也好好复习一下. 楼主翻开了神书<深入理解Java虚拟机>第二版 ...

  9. java120经典面试题

    经典面试题 -----version 1.0 题注:以下答案仅限本人个人见解,若有错误和建议请多多指教.QQ:1807812486 题目来源 1.什么是Java虚拟机?为什么Java被称作是" ...

  10. Groovy语法基础

    Groovy 简介 Groovy 是一种基于 JVM 的动态语言,他的语法和 Java 相似,最终也是要编译 .class 在JVM上运行. Groovy 完全兼容 Java 并且在此基础上添加了很多 ...