https://www.lydsy.com/JudgeOnline/problem.php?id=2243

新学的树剖,在维护的时候线段树维护区间内颜色数量以及左右两端的颜色。统计的时候区间合并时判断中间的合并点颜色是否相等,相等则ans -1

在计算答案的时候不同的链上两端跳的过程中也要注意color[top[u]]和color[fa[top[u]]]是否相等,相等则ans--

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int head[maxn],tot;
struct Edge{
int to,next;
}edge[maxn * ];
void init(){
for(int i = ; i <= N ; i ++) head[i] = -;
tot = ;
}
void add(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
//树的信息
int dep[maxn],hson[maxn],fa[maxn],Size[maxn],color[maxn],Index[maxn],top[maxn];
int nw[maxn];
void dfs1(int t,int la){
Size[t] = ;
hson[t] = ; int MAX = ;
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == la) continue;
dep[v] = dep[t] + ; fa[v] = t;
dfs1(v,t);
Size[t] += Size[v];
if(Size[v] > MAX){
MAX = Size[v];
hson[t] = v;
}
}
}
int cnt = ;
void dfs2(int t,int la){
top[t] = la;
Index[t] = ++cnt;
nw[cnt] = color[t];
if(hson[t]) dfs2(hson[t],la);
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == hson[t] || v == fa[t]) continue;
dfs2(v,v);
}
}
//线段树
struct Tree{
int l,r;
int sum;
int lazy;
int lc,rc;
}tree[maxn << ];
void Pushup(int t){
tree[t].sum = tree[t << ].sum + tree[t << | ].sum;
tree[t].lc = tree[t << ].lc; tree[t].rc = tree[t << | ].rc;
if(tree[t << ].rc == tree[t << | ].lc) tree[t].sum--;
}
void Build(int t,int l,int r){
tree[t].lazy = ;
tree[t].l = l; tree[t].r = r;
if(tree[t].l == tree[t].r){
tree[t].sum = ;
tree[t].lc = tree[t].rc = nw[l];
return;
}
int m = (l + r) >> ;
Build(t << ,l,m); Build(t << | ,m + ,r);
Pushup(t);
}
void Pushdown(int t){
if(tree[t].lazy){
tree[t << ].lazy = tree[t << | ].lazy = tree[t].lazy;
tree[t << ].sum = tree[t << | ].sum = ;
tree[t << ].lc = tree[t << | ].lc = tree[t].lazy;
tree[t << ].rc = tree[t << | ].rc = tree[t].lazy;
tree[t].lazy = ;
}
}
void update(int t,int l,int r,int c){
if(l <= tree[t].l && tree[t].r <= r){
tree[t].lazy = c;
tree[t].sum = ;
tree[t].lc = tree[t].rc = c;
return;
}
Pushdown(t);
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) update(t << ,l,r,c);
else if(l > m) update(t << | ,l,r,c);
else{
update(t << ,l,m,c);
update(t << | ,m + ,r,c);
}
Pushup(t);
}
int query(int t,int l,int r){
if(l <= tree[t].l && tree[t].r <= r) return tree[t].sum;
Pushdown(t);
int ans = ;
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) ans = query(t << ,l,r);
else if(l > m) ans = query(t << | ,l,r);
else{
ans = query(t << ,l,m) + query(t << | ,m + ,r);
if(tree[t << ].rc == tree[t << | ].lc) ans--;
}
Pushup(t);
return ans;
}
int query(int t,int p){
if(tree[t].sum == ) return tree[t].lc;
int m = (tree[t].l + tree[t].r) >> ;
if(p <= m) return query(t << ,p);
else if(p > m) return query(t << | ,p);
}
//树链剖分
void update(int u,int v,int c){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u,v);
update(,Index[top[u]],Index[u],c);
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u,v);
update(,Index[u],Index[v],c);
}
int Query(int u,int v){
int ans = ;
int la = ;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u,v);
ans += query(,Index[top[u]],Index[u]);
if(query(,Index[fa[top[u]]]) == query(,Index[top[u]])) ans--;
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u,v);
ans += query(,Index[u],Index[v]);
return ans;
}
int main(){
Sca2(N,M); init();
for(int i = ; i <= N ; i ++) color[i] = read();;
for(int i = ; i < N ; i ++){
int u = read(),v = read();
add(u,v); add(v,u);
}
int root = N; dep[root] = ;
dfs1(root,-); cnt = ; dfs2(root,root);
Build(,,N);
while(M--){
char op[]; int a,b,c;
scanf("%s",op); a = read(); b = read();
if(op[] == 'C'){
c = read(); update(a,b,c);
}else{
Pri(Query(a,b));
}
}
return ;
}

bzoj2243 树链剖分的更多相关文章

  1. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  2. bzoj2243树链剖分+染色段数

    终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...

  3. bzoj2243树链剖分+区间合并

    树链上区间合并的问题比区间修改要复杂,因为每一条重链在线段树上分布一般都是不连续的,所以在进行链上操作时要手动将其合并起来,维护两个端点值 处理时的方向问题:lca->u是一个方向,lca-&g ...

  4. [SDOI2011]染色 BZOJ2243 树链剖分+线段树

    分析: 区间合并,lcol是左端点的颜色编号,rcol是右端点的颜色编号,那么我们向上合并的时候,如果左儿子的rcol等于右儿子的lcol那么区间的sum--. 另外,如果重链顶的颜色等于重链顶的父节 ...

  5. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  6. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

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

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

  8. [BZOJ2243][SDOI2011]染色 解题报告|树链剖分

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

  9. bzoj-2243 2243: [SDOI2011]染色(树链剖分)

    题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6267  Solved: 2291 Descript ...

随机推荐

  1. Bash 5.0 发布及其新功能

    导读 邮件列表证实最近发布了 Bash-5.0.而且,令人兴奋的是它还有新的功能和变量.如果你一直在使用 Bash 4.4.XX,那么你一定会喜欢 Bash 的第五个主要版本. 第五个版本侧重于新的 ...

  2. BZOJ1444[Jsoi2009]有趣的游戏——AC自动机+概率DP+矩阵乘法

    题目描述 输入 注意 是0<=P, n , l, m≤ 10. 输出 样例输入 input 1 3 2 2 1 2 1 2 AB BA AA input 2 3 4 2 1 2 1 2 AABA ...

  3. POJ 3580-SuperMemo-splay树

    很完整的splay操作.做了这题就可以当板子用了. #include <cstdio> #include <algorithm> #include <cstring> ...

  4. python调用opencv库教程

    OpenCV安装pip install --upgrade setuptoolspip install numpy Matplotlibpip install opencv-python OpenCV ...

  5. 洛谷P1434滑雪题解及记忆化搜索的基本步骤

    题目 滑雪是一道dp及记忆化搜索的经典题目. 所谓记忆化搜索便是在搜索的过程中边记录边搜索的一个算法. 当下次搜到这里时,便直接使用. 而且记忆化搜索一定要满足无后效性,为什么呢,因为如果不满足无后效 ...

  6. MT【295】线段比的仿射变换

    已知$F_1,F_2$分别为椭圆$\dfrac{x^2}{4}+\dfrac{y^2}{3}=1$的左右焦点.$A,B,C$是椭圆上$x$轴上方的三点,且$AF_1//BO//CF_2$,则$\dfr ...

  7. web前端监控的三个方面探讨

    一. js错误监控方式 1. 主动判断 我们在一些运算之后,得到一个期望的结果,然而结果不是我们想要的 // test.js function calc(){ // code... return va ...

  8. 【BZOJ5291】[BJOI2018]链上二次求和(线段树)

    [BZOJ5291][BJOI2018]链上二次求和(线段树) 题面 BZOJ 洛谷 题解 考虑一次询问\([l,r]\)的答案.其中\(S\)表示前缀和 \(\displaystyle \sum_{ ...

  9. hdu 2516(Fibonacci博弈博弈)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2516 Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任意多个, ...

  10. deque双端队列容器

    //deque双端队列容器 //deque双端队列容器与vector一样,采用线性表顺序存储结构,但与vector不同的是, //deque采用的分块线性存储结构来存储数据,每块的大小一般为512字节 ...