传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

裸的树链剖分,最开始我保存一个线段树节点的color值时(若有多种颜色则为-1),不小心使“若其两个子节点color相等,则该节点color值为其儿子的color,并把这个节点内颜色个数设为1”,这是致命的错误——万一两个儿子color都为-1呢?

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm> const int maxn = 100005, maxm = 100005; int n, m, ini_c[maxn], t1, t2, t3, root;
int head[maxn], to[maxn << 1], next[maxn << 1], lb;
int fa[maxn], heavy[maxn], top[maxn], siz[maxn], dep[maxn], id[maxn], a[maxn], cnt;
char opr;
struct Node {
int ql, qr, c, num, lc, rc;
} tree[maxn << 2]; inline void ist(int aa, int ss) {
to[lb] = ss;
next[lb] = head[aa];
head[aa] = lb;
++lb;
}
void dfs1(int r, int dp) {
dep[r] = dp;
siz[r] = 1;
if (r == 6671) {
++r;
--r;
}
for (int j = head[r]; j != -1; j = next[j]) {
if (to[j] != fa[r]) {
fa[to[j]] = r;
dfs1(to[j], dp + 1);
siz[r] += siz[to[j]];
if (siz[to[j]] > siz[heavy[r]]) {
heavy[r] = to[j];
}
}
}
}
void dfs2(int r, int tp) {
if (!r) {
return;
}
id[r] = ++cnt;
a[cnt] = ini_c[r];
top[r] = tp;
dfs2(heavy[r], tp);
for (int j = head[r]; j != -1; j = next[j]) {
if (to[j] != fa[r] && to[j] != heavy[r]) {
dfs2(to[j], to[j]);
}
}
}
void make_tree(int p, int left, int right) {
tree[p].ql = left;
tree[p].qr = right;
if (left == right) {
tree[p].c = tree[p].lc = tree[p].rc = a[left];
tree[p].num = 1;
return;
}
int mid = (left + right) >> 1;
make_tree(p << 1, left, mid);
make_tree(p << 1 | 1, mid + 1, right);
if (tree[p << 1].c == tree[p << 1 | 1].c && tree[p << 1].c != -1) {
tree[p].c = tree[p].lc = tree[p].rc = tree[p << 1].c;
tree[p].num = 1;
}
else {
tree[p].c = -1;
tree[p].lc = tree[p << 1].lc;
tree[p].rc = tree[p << 1 | 1].rc;
tree[p].num = tree[p << 1].num + tree[p << 1 | 1].num;
if (tree[p << 1].rc == tree[p << 1 | 1].lc) {
--tree[p].num;
}
}
}
void upd(int p, int left, int right, int c) {
if (tree[p].ql == left && tree[p].qr == right) {
tree[p].c = tree[p].lc = tree[p].rc = c;
tree[p].num = 1;
return;
}
if (tree[p].c >= 0) {
if (tree[p].c == c) {
return;
}
tree[p << 1].c = tree[p << 1 | 1].c = tree[p].c;
tree[p << 1].lc = tree[p << 1].rc = tree[p].c;
tree[p << 1 | 1].lc = tree[p << 1 | 1].rc = tree[p].c;
tree[p << 1].num = tree[p << 1 | 1].num = 1;
tree[p].c = -1;
}
int mid = (tree[p].ql + tree[p].qr) >> 1;
if (right <= mid) {
upd(p << 1, left, right, c);
}
else if (left > mid) {
upd(p << 1 | 1, left, right, c);
}
else {
upd(p << 1, left, mid, c);
upd(p << 1 | 1, mid + 1, right, c);
}
tree[p].c = -1;
tree[p].lc = tree[p << 1].lc;
tree[p].rc = tree[p << 1 | 1].rc;
tree[p].num = tree[p << 1].num + tree[p << 1 | 1].num;
if (tree[p << 1].rc == tree[p << 1 | 1].lc) {
--tree[p].num;
}
}
int qry(int p, int left, int right, int & lc, int & rc) {
if (tree[p].ql == left && tree[p].qr == right) {
lc = tree[p].lc;
rc = tree[p].rc;
return tree[p].num;
}
if (tree[p].c >= 0) {
lc = rc = tree[p].c;
return 1;
}
int mid = (tree[p].ql + tree[p].qr) >> 1;
if (right <= mid) {
return qry(p << 1, left, right, lc, rc);
}
else if (left > mid) {
return qry(p << 1 | 1, left, right, lc, rc);
}
else {
int tlc, trc, rt1, rt2;
rt1 = qry(p << 1, left, mid, lc, trc);
rt2 = qry(p << 1 | 1, mid + 1, right, tlc, rc);
return rt1 + rt2 - (trc == tlc? 1: 0);
}
}
inline void C(int u, int v, int c) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) {
std::swap(u, v);
}
upd(1, id[top[u]], id[u], c);
u = fa[top[u]];
}
if (dep[u] < dep[v]) {
std::swap(u, v);
}
upd(1, id[v], id[u], c);
}
inline int Q(int u, int v) {
int rt = 0;
int u_lc1 = -666, u_rc1 = -666, u_lc2 = -666, u_rc2 = -666;
int v_lc1 = -666, v_rc1 = -666, v_lc2 = -666, v_rc2 = -666;
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) {
rt += qry(1, id[top[u]], id[u], u_lc2, u_rc2);
if (u_rc2 == u_lc1) {
--rt;
}
u_lc1 = u_lc2;
u_rc1 = u_rc2;
u = fa[top[u]];
}
else {
rt += qry(1, id[top[v]], id[v], v_lc2, v_rc2);
if (v_rc2 == v_lc1) {
--rt;
}
v_lc1 = v_lc2;
v_rc1 = v_rc2;
v = fa[top[v]];
}
}
if (dep[u] > dep[v]) {
rt += qry(1, id[v], id[u], u_lc2, u_rc2);
if (u_rc2 == u_lc1) {
--rt;
}
if (u_lc2 == v_lc1) {
--rt;
}
}
else {
rt += qry(1, id[u], id[v], v_lc2, v_rc2);
if (v_rc2 == v_lc1) {
--rt;
}
if (v_lc2 == u_lc1) {
--rt;
}
}
return rt;
} int main(void) {
//freopen("paint.in", "r", stdin);
//freopen("paint.out", "w", stdout);
memset(head, -1, sizeof head);
memset(next, -1, sizeof next);
unsigned seed;
scanf("%d%d", &n, &m);
seed += n + m;
for (int i = 1; i <= n; ++i) {
scanf("%d", ini_c + i);
seed += ini_c[i];
}
for (int i = 1; i < n; ++i) {
scanf("%d%d", &t1, &t2);
ist(t1, t2);
ist(t2, t1);
seed += t1;
} srand(seed);
root = rand() % n + 1;
//root = 1;
dfs1(root, 0);
dfs2(root, root);
make_tree(1, 1, n); while (m--) {
while ((opr = getchar()) < 'A');
if (opr == 'C') {
scanf("%d%d%d", &t1, &t2, &t3);
C(t1, t2, t3);
}
else {
scanf("%d%d", &t1, &t2);
printf("%d\n", Q(t1, t2));
}
}
return 0;
}

  

_bzoj2243 [SDOI2011]染色【树链剖分】的更多相关文章

  1. BZOJ 2243: [SDOI2011]染色 [树链剖分]

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

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

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

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

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

  4. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

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

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

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

  6. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

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

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

  8. 2243: [SDOI2011]染色(树链剖分+线段树)

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

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

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

  10. [bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]

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

随机推荐

  1. Enhance Magento 404 page

    Magento default installation already has a predefined custom 404 page (no-route). But is it enough t ...

  2. Mysql不同存储引擎的表转换方法

    Mysql不同存储引擎的表转换方法 1.Alter table直接修改表的存储引擎,但是这样会导致大量的系统开销,Mysql为此要执行一个就表向新表的逐行复制.在此期间,转换操作可能会占用服务器的所有 ...

  3. ZOJ 3316 Game 一般图最大匹配带花树

    一般图最大匹配带花树: 建图后,计算最大匹配数. 假设有一个联通块不是完美匹配,先手就能够走那个没被匹配到的点.后手不论怎么走,都必定走到一个被匹配的点上.先手就能够顺着这个交错路走下去,最后一定是后 ...

  4. js实现的美女瀑布流效果代码

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  5. 基于github for windows&amp;github的团队协作基本操作

    首先,我们要在github上团队协作.先要建立一个team.这个自行百度,在github上操作就是. 点击打开链接 这是我的有道文章(假设看不到图片的话) 今天主要讲的是怎么操作github for ...

  6. 我的家乡:三河古镇已经登上央视CCTV-1新闻联播啦!

    在烟雨朦胧时走在古镇的青石街上,别有一番风味!第一幅图为央视的直播车,第二副图为漂亮的三河夜景色!

  7. mt7620 uboot

    我本机装的是64位Ubuntu, SDK 里提供的 buildroot-gcc342 是32位的,无法直接运行,需要先安装 gcc-multilib. sudo apt-get install gcc ...

  8. Dynamics CRM 修改Excel 最大导出记录限制及 最大上传文件限制

    CRM默认的Excel最大导出记录是10000条,最大上传文件限制为5m. 这样的限制可以满足少量数据的批量更新,但是如果数据量比较大的话需要修改最大的导出记录限制,和上传文件的大小,网上有的是直接修 ...

  9. IDE配置jvm参数

    -------- IntelliJ IDEA 配置参数:-Xms34m -Xmx234m 内存初始化大小,最小和最大值: 测试代码: public class JVMDemoTest { public ...

  10. bzoj4593: [Shoi2015]聚变反应炉

    这道题的难点其实是在设DP方程,见过就应该会了 令f0,i表示先激发i的父亲,再激发i,把i的整棵子树都激发的最小费用 f1,i表示先激发i,再激发i的父亲,把i的整棵子树都激发的最小费用 设x,y为 ...