题目链接 BZOJ2243

树链剖分 $+$ 线段树

线段树每个节点维护$lc$, $rc$, $s$

$lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色

$s$代表该区间的所有连续颜色段数(仅考虑该区间)

$lazy$表示延迟信息。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define lson i << 1, L, mid
#define rson i << 1 | 1, mid + 1, R typedef long long LL; const int N = 1e5 + 10;
const int A = 21; vector <int> v[N];
int n, m;
int c[N];
int f[N][A];
int lazy[N << 2], s[N << 2], lc[N << 2], rc[N << 2];
int h[N], deep[N], sz[N];
int son[N];
int tot = 0;
int top[N]; int LCA(int a, int b){
if (deep[a] < deep[b]) swap(a, b);
for (int i = 0, delta = deep[a] - deep[b]; delta; delta >>= 1, ++i) if (delta & 1) a = f[a][i];
if (a == b) return a;
dec(i, 19, 0) if (f[a][i] != f[b][i]) a = f[a][i], b = f[b][i];
return f[a][0];
} inline void pushup(int i){
lc[i] = lc[i << 1];
rc[i] = rc[i << 1 | 1];
if (rc[i << 1] ^ lc[i << 1 | 1]) s[i] = s[i << 1] + s[i << 1 | 1];
else s[i] = s[i << 1] + s[i << 1 | 1] - 1;
} inline void pushdown(int i, int L, int R){
int tmp = lazy[i];
if (tmp == -1 || L == R) return; s[i << 1] = s[i << 1 | 1] = 1;
lazy[i << 1] = lazy[i << 1 | 1] = tmp; lc[i << 1] = rc[i << 1] = tmp;
lc[i << 1 | 1] = rc[i << 1 | 1] = tmp;
lazy[i] = -1;
} void dfs1(int x, int fa, int dep){
sz[x] = 1;
deep[x] = dep; if (fa){
f[x][0] = fa;
for (int i = 0; f[f[x][i]][i]; ++i) f[x][i + 1] = f[f[x][i]][i];
} int ct = (int)v[x].size(); rep(i, 0, ct - 1){
int u = v[x][i];
if (u == fa) continue;
dfs1(u, x, dep + 1);
sz[x] += sz[u];
if (sz[son[x]] < sz[u]) son[x] = u;
}
} void dfs2(int x, int tp){
h[x] = ++tot;
top[x] = tp;
if (son[x]) dfs2(son[x], tp); int ct = (int)v[x].size();
rep(i, 0, ct - 1){
int u = v[x][i];
if (u == f[x][0] || u == son[x]) continue;
dfs2(u, u);
}
} void build(int i, int L, int R){
s[i] = 1;
lazy[i] = -1; if (L == R) return;
int mid = (L + R) >> 1; build(lson);
build(rson);
} void change(int i, int L, int R, int l, int r, int val){
pushdown(i, L, R);
if (L == l && R == r){
lc[i] = rc[i] = val;
s[i] = 1;
lazy[i] = val;
return;
} int mid = (L + R) >> 1;
if (r <= mid) change(lson, l, r, val);
else if (l > mid) change(rson, l, r, val);
else{
change(lson, l, mid, val);
change(rson, mid + 1, r, val);
} pushup(i);
} int query(int i, int L, int R, int l, int r){
pushdown(i, L, R);
if (L == l && R == r) return s[i]; int mid = (L + R) >> 1;
if (r <= mid) return query(lson, l, r);
else if (l > mid) return query(rson, l, r);
else{
int tmp = 1;
if (rc[i << 1] ^ lc[i << 1 | 1]) tmp = 0;
return query(lson, l, mid) + query(rson, mid + 1, r) - tmp;
}
} int getcolor(int i, int L, int R, int x){
pushdown(i, L, R);
if (L == R) return lc[i];
int mid = (L + R) >> 1;
if (x <= mid) return getcolor(lson, x);
else return getcolor(rson, x);
} int solvesum(int x, int tp){
int ret = 0;
for (; top[x] ^ top[tp] ;){
ret += query(1, 1, n, h[top[x]], h[x]);
if (getcolor(1, 1, n, h[top[x]]) == getcolor(1, 1, n, h[f[top[x]][0]])) --ret;
x = f[top[x]][0];
} ret += query(1, 1, n, h[tp], h[x]);
return ret;
} void solvechange(int x, int tp, int val){
for (; top[x] ^ top[tp]; ){
change(1, 1, n, h[top[x]], h[x], val);
x = f[top[x]][0];
} change(1, 1, n, h[tp], h[x], val);
} void solve(){
int x, y, z;
dfs1(1, 0, 0);
dfs2(1, 1);
build(1, 1, n);
rep(i, 1, n) change(1, 1, n, h[i], h[i], c[i]); rep(i, 1, m){
char ch[10];
scanf("%s", ch);
if (ch[0] == 'Q'){
scanf("%d%d", &x, &y);
int t = LCA(x, y);
printf("%d\n", solvesum(x, t) + solvesum(y, t) - 1);
}
else{
scanf("%d%d%d", &x, &y, &z);
int t = LCA(x, y);
solvechange(x, t, z);
solvechange(y, t, z);
}
}
} void init(){
scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%d", c + i);
rep(i, 2, n){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
}
} int main(){
init();
solve();
return 0;
}

BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)的更多相关文章

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

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

  2. bzoj2243[SDOI2011]染色 树链剖分+线段树

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

  3. B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

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

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

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

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

  6. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  7. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  8. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  9. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

随机推荐

  1. Find a way HDU - 2612(bfs)

    Find a way Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  2. CodeForces - 899E Segments Removal (优先队列 + 链表)

    给定一个序列,每次从序列中找一个长度最大的元素相同的片段,删除它. 如果长度相同,删除最靠左边的那个片段. 问,需要删几次. 用链表处理删除片段.对于删除之后两边又能连成一个片段的那种情况,用set记 ...

  3. ACM-ICPC 2015 Shenyang Preliminary Contest B. Best Solver

    The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart. ...

  4. 如何查看Android apk的包名?

    有以下四种方法可以查看apk的包名,之后有别的方法,会接着更新文档的. 1. 安装APK包名查看器; 2. 源码AndroidManifest.xml中查看package包名; 3. 利用" ...

  5. springboot-vue-自定义注解限制接口调用

    新建注解: /** * 想要权限拦截的接口就加上这个注解 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Doc ...

  6. 基于AOP的优惠券发送异常哨兵监控

    本文来自网易云社区 作者:王贝 最近总是发现支付发红包优惠券发完的情况,但是发现的比较迟缓,于是乎,想加一个哨兵监控,统计了一下,组内不少需求都有发送优惠券的行为,也是经常遇到发送异常的情况,所以,想 ...

  7. python - work5 - 类与对象

    # -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: work_20181119.py@ide: PyCharm Communit ...

  8. 《机器学习实战》笔记——AdaBoost

    笔记见备注 # _*_ coding:utf-8 _*_ from numpy import * # 简单数据集 def loadSimpData(): datMat = matrix([[1., 2 ...

  9. [python][oldboy] * **的用法

    * 和**主要用在函数的参数中, # coding=utf8 """ 三种编码: 1 python程序代码的编码 # coding=utf8 2 设置/查看python程 ...

  10. TOJ4505: KOSARE

    TOJ4505: KOSARE  Time Limit(Common/Java):10000MS/30000MS     Memory Limit:65536KByteTotal Submit: 11 ...