BZOJ 2243 SDOI 2011染色
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
算法讨论:
树链剖分把树放到线段树上。然后线段树的每个节点要维护的东西有左端点的颜色,右端点的颜色,以及是否被改变过颜色,和颜色段数。
向上合并的过程中,要注意如果左孩子的右端点和右孩子的左端点颜色相同,那么就要把颜色段数减一。
然后我们考虑询问的问题:
对于一个询问,我们是按深度从下向上跳着计算的,所以每次统计一个路径的时候,我们要记录上一次的路径的两端点的颜色,如果本次路径计算的
右端点颜色和上次的左端点颜色相同,那么答案就要减去1.(注意树链剖分,如果在同一次线段树内查询,那么节点深度小的一定线段树的编号也小)。
当两个节点跳到一个重链上的时候,那么此时两边的颜色都要进行判断一下。至于为啥,很好想吧。
题目代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype> using namespace std;
const int N = + ;
inline int read() {
int x = ;
char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) {
x = x * + c - '';
c = getchar();
}
return x;
} struct SegmentTree {
int lc, rc, l, r, tag, sz;
}Node[N * ];
struct Edge {
int from, to, next;
}edges[N << ]; char ss[];
int n, m, cnt, pos, co[N], lco, rco;
int fa[N], head[N], son[N], size[N];
int num[N], top[N], depth[N], seg[N]; void insert(int from, int to) {
++ cnt;
edges[cnt].from = from; edges[cnt].to = to;
edges[cnt].next = head[from]; head[from] = cnt;
} void dfs_1(int u, int f) {
fa[u] = f; size[u] = ;
for(int i = head[u]; i; i = edges[i].next) {
int v = edges[i].to;
if(v != f) {
depth[v] = depth[u] + ;
dfs_1(v, u);
size[u] += size[v];
if(!son[u] || size[v] > size[son[u]])
son[u] = v;
}
}
} void dfs_2(int u, int ances) {
top[u] = ances;
num[u] = ++ pos;
seg[pos] = u;
if(!son[u]) return;
dfs_2(son[u], ances);
for(int i = head[u]; i; i = edges[i].next) {
int v = edges[i].to;
if(v != fa[u] && v != son[u]) {
dfs_2(v, v);
}
}
} void pushdown(int o) {
if(Node[o].l == Node[o].r) return;
int l = o << , r = o << | ;
if(Node[o].tag) {
Node[l].tag = Node[r].tag = Node[o].tag;
Node[l].lc = Node[l].rc = Node[o].tag;
Node[r].lc = Node[r].rc = Node[o].tag;
Node[l].sz = Node[r].sz = ;
Node[o].tag = ;
}
} void pushup(int o) {
if(Node[o].l == Node[o].r) return;
int l = o << , r = o << | ;
Node[o].lc = Node[l].lc;
Node[o].rc = Node[r].rc;
Node[o].sz = Node[l].sz + Node[r].sz - (Node[l].rc == Node[r].lc);
} void build(int o, int l, int r) {
Node[o].l = l; Node[o].r = r; Node[o].tag = ;
if(l == r) {
Node[o].sz = ;
Node[o].lc = Node[o].rc = co[seg[l]];
return;
}
int mid = (l + r) >> ;
build(o << , l, mid); build(o << | , mid + , r);
pushup(o);
} void update(int o, int l, int r, int v) {
if(Node[o].l == l && Node[o].r == r) {
Node[o].lc = Node[o].rc = v;
Node[o].tag = v; Node[o].sz = ;
return;
}
int mid = (Node[o].l + Node[o].r) >> ;
pushdown(o);
if(r <= mid) update(o << , l, r, v);
else if(l > mid) update(o << | , l, r, v);
else {
update(o << , l, mid, v);
update(o << | , mid + , r, v);
}
pushup(o);
} int query(int o, int l, int r, int L, int R) {
if(Node[o].l == L) lco = Node[o].lc;
if(Node[o].r == R) rco = Node[o].rc;
if(Node[o].l == l && Node[o].r == r) {
return Node[o].sz;
}
int mid = (Node[o].l + Node[o].r) >> ;
pushdown(o);
if(r <= mid) return query(o << , l, r, L, R);
else if(l > mid) return query(o << | , l, r, L, R);
else {
return query(o << , l, mid, L, R) + query(o << | , mid + , r, L, R) - (Node[o << ].rc == Node[o << | ].lc);
}
pushup(o);
} void Update(int x, int y, int z) {
int f1 = top[x], f2 = top[y];
while(f1 != f2) {
if(depth[f1] < depth[f2]) {
swap(x, y); swap(f1, f2);
}
update(, num[f1], num[x], z);
x = fa[f1]; f1 = top[x];
}
if(depth[x] < depth[y]) {
update(, num[x], num[y], z);
}
else {
update(, num[y], num[x], z);
}
} int Query(int x, int y) {
int f1 = top[x], f2 = top[y], res = ;
int ans1 = -, ans2 = -;
while(f1 != f2) {
if(depth[f1] < depth[f2]) {
swap(f1, f2); swap(x, y);
swap(ans1, ans2);
}
res += query(, num[f1], num[x], num[f1], num[x]);
if(rco == ans1) res --; ans1 = lco;
x = fa[f1]; f1 = top[x];
}
if(depth[x] < depth[y]) {
swap(x, y); swap(ans1, ans2);
}
res += query(, num[y], num[x], num[y], num[x]);
if(rco == ans1) res --;
if(lco == ans2) res --;
return res;
} int main() {
int x, y, z;
n = read(); m = read();
for(int i = ; i <= n; ++ i) co[i] = read();
for(int i = ; i < n; ++ i) {
x = read(); y = read();
insert(x, y); insert(y, x);
}
depth[] = ;
dfs_1(, -); dfs_2(, );
build(, , n);
for(int i = ; i <= m; ++ i) {
scanf("%s", ss);
if(ss[] == 'C') {
x = read(); y = read(); z = read();
Update(x, y, z);
}
else {
x = read(); y = read();
printf("%d\n", Query(x, y));
}
}
return ;
}
BZOJ2243
BZOJ 2243 SDOI 2011染色的更多相关文章
- [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】
题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...
- [SDOI 2011]染色
Description 题库链接 给定一棵有 \(n\) 个节点的无根树和 \(m\) 个操作,操作有 \(2\) 类: 将节点 \(a\) 到节点 \(b\) 路径上所有点都染成颜色 \(c\) : ...
- [BZOJ 2242] [SDOI 2011] 计算器
Description 你被要求设计一个计算器完成以下三项任务: 给定 \(y,z,p\),计算 \(y^z \bmod p\) 的值: 给定 \(y,z,p\),计算满足 \(xy≡ z \pmod ...
- [BZOJ 2285] [SDOI 2011] 保密
Description 传送门 Solution 这道题的最大难点在于读懂题意(雾 分数规划求出 \(n\) 到 \(1\cdots n_1\) 每个点的最小 \(\sum\frac{t_i}{s_i ...
- 解题: SDOI 2011 染色
题面 强行把序列问题通过树剖套在树上...算了算是回顾了一下树剖的思想=.= 每次树上跳的时候注意跳的同时维护当前拼出来的左右两条链的靠上的端点,然后拼起来的时候讨论一下拼接点,最后一下左右两边的端点 ...
- BZOJ 2245 SDOI 2011 工作安排 费用流
题目大意:有一些商品须要被制造.有一些员工.每个员工会做一些物品,然而这些员工做物品越多,他们的愤慨值越大,这满足一个分段函数.给出哪些员工能够做哪些东西,给出这些分段函数,求最小的愤慨值以满足须要被 ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- BZOJ 2243 染色(树链剖分好题)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 7971 Solved: 2990 [Submit][Stat ...
- [BZOJ 1879][SDOI 2009]Bill的挑战 题解(状压DP)
[BZOJ 1879][SDOI 2009]Bill的挑战 Description Solution 1.考虑状压的方式. 方案1:如果我们把每一个字符串压起来,用一个布尔数组表示与每一个字母的匹配关 ...
随机推荐
- [Unity优化] Unity CPU性能优化
前段时间本人转战unity手游,由于作者(Chwen)之前参与端游开发,有些端游的经验可以直接移植到手游,比如项目框架架构.代码设计.部分性能分析,而对于移动终端而言,CPU.内存.显卡甚至电池等硬件 ...
- 翻译:《What can I hold you with?》—— 博尔赫斯《英文诗两首》之一。
What can I hold you with? 我拿什么才能留住你? I offer you lean streets, desperate sunsets, the moon of the ja ...
- 《APUE》读书笔记第十二章-线程控制
本章中,主要是介绍控制线程行为方面的内容,同时介绍了在同一进程中的多个线程之间如何保持数据的私有性以及基于进程的系统调用如何与线程进行交互. 一.线程属性 我们在创建线程的时候可以通过修改pthrea ...
- 解决APP中fragment重叠问题
由于内存重启,导致的frgament重叠,其原因就是FragmentState没有保存Fragment的显示状态,即mHidden,导致页面重启后,该值为默认的false,即show状态,所以导致了F ...
- CommandBehavior.CloseConnection的使用
CommandBehavior.CloseConnection的使用 分析问题 由于流模式读取数据库的特点,在具体应用时很难确定数据库连接何时才能被关闭,因为读取的动作是连续进行的,下面是一个常见的数 ...
- 解决ScrollView 与ListView共存显示不完全的问题
ScrollView与ListView共存会存在滚动的问题,并且ListView只显示一个半Item. 当ListView的高度设定一定的值时,ListView同样地会显示对应的高度的Item. 因此 ...
- 自制单片机之五……LCD12864的驱动
LCD12864的驱动LCD12864在市面上主要分为两种,一种是采用st7920控制器的,它一般带有中文字库字模,价格略高一点.另一种是采用KS0108控制器,它只是点阵模式,不带字库.很可惜,我的 ...
- 计算机语言学习导论[C/C++]
作者:@幻の上帝 1 前置条件语文其实挺重要,这个没问题,但容易被忽视.当然,如果不是经常要折腾文档,要求不高:但起码要能说清楚话.数学重要,主要是广度,作为快速学习相关领域知识的基础.深度上面可深可 ...
- 【转】解决java.lang.IllegalStateException: The content of the adapter has changed but ListView...的问题
原文网址:http://blog.csdn.net/ueryueryuery/article/details/20607845 我写了一个Dialog,Dialog中有一个ListView,想要点Li ...
- bzoj 1195
http://www.lydsy.com/JudgeOnline/problem.php?id=1195 状压DP. 首先去掉被包含的字符串. 对于字符串i和j,我们求出 当字符串j的左端点在字符串i ...