洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)
题目链接
题解
比较裸的树链剖分 好像树链剖分的题都很裸
线段树中维护一个区间最左和最右的颜色,和答案
合并判断一下中间一段就可以了
比较考验代码能力
Code
#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;
inline int gi() {
int f = 1, s = 0;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -1, c = getchar();
while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
return f == 1 ? s : -s;
}
const int N = 100010;
struct node {
int to, next;
}g[N<<1];
int last[N], gl;
inline void add(int x, int y) {
g[++gl] = (node) {y, last[x]};
last[x] = gl;
g[++gl] = (node) {x, last[y]};
last[y] = gl;
return ;
}
int c[N];
struct Segment_tree {
int l, r, v, lazy;
}t[N<<2];
int fa[N], siz[N], son[N], cnt, s[N], top[N], id[N], dep[N];
void dfs1(int u, int f) {
siz[u] = 1; fa[u] = f;
int MAX = 0;
for (int i = last[u]; i; i = g[i].next) {
int v = g[i].to;
if (v == f) continue;
dep[v] = dep[u]+1;
dfs1(v, u);
siz[u] += siz[v];
if (MAX < siz[v]) MAX = siz[v], son[u] = v;
}
return ;
}
void dfs2(int u, int topf) {
top[u] = topf;
s[++cnt] = c[u];
id[u] = cnt;
if (!son[u]) return ;
dfs2(son[u], topf);
for (int i = last[u]; i; i = g[i].next) {
int v = g[i].to;
if (v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
return ;
}
#define mid ((l+r)>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
void pushup(int rt) {
t[rt].l = t[ls].l; t[rt].r = t[rs].r;
t[rt].v = t[ls].v + t[rs].v;
if (t[ls].r == t[rs].l) t[rt].v--;
return ;
}
void build(int rt, int l, int r) {
if (l == r) {
t[rt] = (Segment_tree) {s[l], s[l], 1, 0};
return ;
}
build(ls, l, mid); build(rs, mid+1, r);
pushup(rt);
return ;
}
void pushdown(int rt) {
int lazy = t[rt].lazy;
t[rt].lazy = 0;
if (lazy) {
t[rs].lazy = t[ls].lazy = lazy;
t[rs].l = t[rs].r = t[ls].l = t[ls].r = lazy;
t[rs].v = t[ls].v = 1;
}
return ;
}
void update(int rt, int l, int r, int L, int R, int k) {
if (L <= l && r <= R) {
t[rt].v = 1;
t[rt].lazy = t[rt].l = t[rt].r = k;
return ;
}
pushdown(rt);
if (L <= mid) update(ls, l, mid, L, R, k);
if (R > mid) update(rs, mid+1, r, L, R, k);
pushup(rt);
return ;
}
struct zzy {
int l, r, v;
};
zzy merge(zzy a, zzy b) {
if (!a.v) return b;
if (!b.v) return a;
return (zzy) {a.l, b.r, a.v+b.v-(a.r == b.l)};
}
zzy query(int rt, int l, int r, int L, int R) {
if (L <= l && r <= R)
return (zzy) {t[rt].l, t[rt].r, t[rt].v};
zzy z = (zzy) {0, 0, 0};
pushdown(rt);
if (L <= mid)
z = query(ls, l, mid, L, R);
if (R > mid)
z = merge(z, query(rs, mid+1, r, L, R));
return z;
}
void upway(int x, int y, int z) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, 1, cnt, id[top[x]], id[x], z);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
update(1, 1, cnt, id[x], id[y], z);
return ;
}
int qway(int x, int y) {
zzy zx, zy;
zx = zy = (zzy) {0, 0, 0};
while (top[x] != top[y]) {
if (dep[top[x]] >= dep[top[y]]) {
zx = merge(query(1, 1, cnt, id[top[x]], id[x]), zx);
x = fa[top[x]];
}
else {
zy = merge(query(1, 1, cnt, id[top[y]], id[y]), zy);
y = fa[top[y]];
}
}
if (dep[x] > dep[y]) swap(x, y), swap(zx, zy);
zy = merge(query(1, 1, cnt, id[x], id[y]), zy);
zx.v += zy.v;
if (zx.l == zy.l) zx.v--;
return zx.v;
}
int main() {
int n = gi(), m = gi();
for (int i = 1; i <= n; i++) c[i] = gi();
for (int i = 1; i < n; i++) add(gi(), gi());
dfs1(1, 0);
dfs2(1, 1);
build(1, 1, n);
while (m--) {
char c; cin>>c;
if (c == 'C') {
int x = gi(), y = gi(), z = gi();
upway(x, y, z);
}
else {
int x = gi(), y = gi();
printf("%d\n", qway(x, y));
}
}
return 0;
}
洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)的更多相关文章
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][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 ...
- B20J_2243_[SDOI2011]染色_树链剖分+线段树
B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- 2243: [SDOI2011]染色 树链剖分+线段树染色
给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221”由3段组 ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树
题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
随机推荐
- inux下安装ab
1,APR 下载地址:http://apr.apache.org/download.cgi 1)tar -zxf apr-1.4.5.tar.gz ./configure --prefix=/u ...
- LaTeX入门教程(一)
LaTeX(LATEX,音译“拉泰赫”)是一种基于ΤΕΧ的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在20世纪80年代初期开发,利用这种格式,即使使用者没有排版和程序设计 ...
- c# 获取非托管指针长度
public List<string> GetPDFValues() { List<string> strs = new List<string>(); unsaf ...
- 特殊的HttpApplication事件处理
在global.asax中,针对HttpApplication的事件处理,可以通过定义特殊命名的方法来实现.首先,这些方法必须符合System.EventHandler,因为所有的HttpApplic ...
- 处理iOS设备的屏幕旋转
某些情况下,不强制的给用户唯一的屏幕角度给用户.这样用户可以旋转手机得到不同的视觉体验. 最简单的就是safari,横看竖看都可以. 这时需要捕捉用户的屏幕旋转事件并处理.很简单,才两步.比把大象装冰 ...
- (转)ASP.NET基础之HttpHandler学习
原文地址:http://www.cnblogs.com/wujy/archive/2013/08/18/3266009.html 经过前两篇[ASP.NET基础之HttpModule学习]和[ASP. ...
- 三羊献瑞——第六届蓝桥杯C语言B组(省赛)第三题
原创 三羊献瑞 观察下面的加法算式: 祥 瑞 生 辉 + 三 羊 献 瑞 ------------------- 三 羊 生 瑞 气 (如果有对齐问题,可以参看[图1.jpg]) 其中,相同的汉字代表 ...
- GitHub小技巧-定义项目语言
GitHub是根据项目里文件数目最多的文件类型,识别项目类型.后端项目难免会包含前端的资源,有时候就会被标记成前端语言,因为项目里 css 等文件比较多, 被误识别成css项目. GitHub不提供指 ...
- android 百度天气接口
百度天气接口 之前有篇随笔是说中国气象的天气接口的,但那个接口不是很稳定,用一段时间过后就会获取不到数据了. 随笔地址:http://www.cnblogs.com/liangstudyhome/p/ ...
- C# Task的使用
1.Task的使用 创建一个Task,有三种方式 //第一种 Task t1 = new Task(() => { Console.WriteLine(DateTime.Now.ToString ...