BZOJ 2243 染色(树链剖分好题)
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 7971 Solved: 2990
[Submit][Status][Discuss]
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题目链接:BZOJ 2243
做了几道普通的树链剖分维护边权、点权,查询路径的题目,感觉并没有什么特点,然而这题比较有意思,求路径上连续颜色有几段,显然用线段树的话只要维护当前区间最左和最右的颜色,左右子区间即可推出父区间的答案:左边段数+右边段数-(左区间右端点颜色==右区间左端点颜色)。然后统计的时候也要利用这个思想——线段树的query与树链剖分中记录u与v上升区间段数的同时也与u、v最后上升的区间最左端点颜色比较得到答案。
代码:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 100010;
struct seg
{int l, mid, r;int lc, rc;int s, tag;
};
struct edge
{int to, nxt;edge() {}edge(int _to, int _nxt): to(_to), nxt(_nxt) {}
};
edge E[N << 1];
seg T[N << 2];
int head[N], tot;
int sz[N], fa[N], son[N], top[N], dep[N], idx[N], ts;
int arr[N];
int Rc, Lc;void init()
{CLR(head, -1);tot = 0;ts = 0;
}
void add(int s, int t)
{E[tot] = edge(t, head[s]);head[s] = tot++;
}
void dfs1(int u, int f, int d)
{sz[u] = 1;fa[u] = f;son[u] = -1;dep[u] = d;for (int i = head[u]; ~i; i = E[i].nxt){int v = E[i].to;if (v != f){dfs1(v, u, d + 1);sz[u] += sz[v];if (son[u] == -1 || sz[son[u]] < sz[v])son[u] = v;}}
}
void dfs2(int u, int tp)
{idx[u] = ++ts;top[u] = tp;if (~son[u])dfs2(son[u], tp);for (int i = head[u]; ~i; i = E[i].nxt){int v = E[i].to;if (v != fa[u] && v != son[u])dfs2(v, v);}
}
void pushup(int k)
{T[k].s = T[LC(k)].s + T[RC(k)].s - (T[LC(k)].rc == T[RC(k)].lc);T[k].lc = T[LC(k)].lc;T[k].rc = T[RC(k)].rc;
}
void pushdown(int k)
{if (T[k].tag == -1)return ;T[LC(k)].tag = T[RC(k)].tag = T[k].tag;T[LC(k)].lc = T[LC(k)].rc = T[k].tag;T[RC(k)].lc = T[RC(k)].rc = T[k].tag;T[LC(k)].s = T[RC(k)].s = 1;T[k].tag = -1;
}
void build(int k, int l, int r)
{T[k].l = l;T[k].r = r;T[k].mid = MID(l, r);T[k].lc = T[k].rc = 0;T[k].tag = -1;T[k].s = 0;if (l == r)return ;build(LC(k), l, T[k].mid);build(RC(k), T[k].mid + 1, r);
}
void update(int k, int l, int r, int c)
{if (l <= T[k].l && T[k].r <= r){T[k].tag = c;T[k].lc = T[k].rc = c;T[k].s = 1;}else{pushdown(k);if (r <= T[k].mid)update(LC(k), l, r, c);else if (l > T[k].mid)update(RC(k), l, r, c);else{update(LC(k), l, T[k].mid, c);update(RC(k), T[k].mid + 1, r, c);}pushup(k);}
}
int query(int k, int l, int r, int L, int R)
{if (L == T[k].l)Lc = T[k].lc;if (R == T[k].r)Rc = T[k].rc;if (l <= T[k].l && T[k].r <= r)return T[k].s;else{pushdown(k);if (r <= T[k].mid)return query(LC(k), l, r, L, R);else if (l > T[k].mid)return query(RC(k), l, r, L, R);elsereturn query(LC(k), l, T[k].mid, L, R) + query(RC(k), T[k].mid + 1, r, L, R) - (T[LC(k)].rc == T[RC(k)].lc);}
}
int Find(int u, int v)
{int ret = 0;int tu = top[u], tv = top[v];int last_u = -1, last_v = -1;while (tu != tv){if (dep[tu] < dep[tv]){swap(tu, tv);swap(u, v);swap(last_u, last_v);}ret += query(1, idx[tu], idx[u], idx[tu], idx[u]);if (Rc == last_u)--ret;last_u = Lc;u = fa[tu];tu = top[u];}if (dep[u] > dep[v]){swap(u, v);swap(last_u, last_v);}ret += query(1, idx[u], idx[v], idx[u], idx[v]);if (Lc == last_u)--ret;if (Rc == last_v)--ret;return ret;
}
void solve(int u, int v, int c)
{int tu = top[u], tv = top[v];while (tu != tv){if (dep[tu] < dep[tv]){swap(tu, tv);swap(u, v);}update(1, idx[tu], idx[u], c);u = fa[tu];tu = top[u];}if (dep[u] > dep[v])swap(u, v);update(1, idx[u], idx[v], c);
}
int main(void)
{int n, m, a, b, c, i;char ops[10];while (~scanf("%d%d", &n, &m)){init();for (i = 1; i <= n; ++i)scanf("%d", &arr[i]);for (i = 1; i < n; ++i){scanf("%d%d", &a, &b);add(a, b);add(b, a);}dfs1(1, 0, 1);dfs2(1, 1);build(1, 1, n);for (i = 1; i <= n; ++i)update(1, idx[i], idx[i], arr[i]);while (m--){scanf("%s", ops);if (ops[0] == 'Q'){scanf("%d%d", &a, &b);printf("%d\n", Find(a, b));}else{scanf("%d%d%d", &a, &b, &c);solve(a, b, c);}}}return 0;
}
转载于:https://www.cnblogs.com/Blackops/p/7258037.html
BZOJ 2243 染色(树链剖分好题)相关推荐
- HYSBZ - 2243染色——树链剖分+线段树建树技巧
[题目描述] HYSBZ - 2243染色 [题目分析] 我一直没有看清楚题,以为求的是路径上出现颜色的种类,然后就写了一个区间染色的线段树进行维护,过样例的时候才发现题读错了,人家要求的是路径上出现 ...
- 小清的树链剖分10题日志01 树链剖分种果子 有你好果子吃的
声明:由于本人能力尚不优 故无法做出解释文章 此文仅为自己日记 感谢你的阅读 作为队里的数据结构选手 2019西安邀请赛的E题 竟然在有机时的情况下 想到了线段树log^2的拆位做法 但是题目路径把自 ...
- 洛谷P3384 - 树链剖分(树链剖分模板题)
题目链接 https://www.luogu.org/problemnew/show/P3384 [描述] 树链剖分模板题,记一下板子 #include<bits/stdc++.h> #d ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- SPOJ- QTREE+HDU 3966(树链剖分裸题
题目:维护一个树,支持修改边长,查询任意两点间距离. 思路:学习了一下树链剖分,还是看了一阵子才看懂的(大概两个多小时orz...)其实总的来说并不是很难,主要是数组比较多,然后看的那篇博客大概是为了 ...
- 洛谷3384(树链剖分模板题)
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- bzoj 3083 遥远的国度——树链剖分+线段树维护子树信息
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 int 的范围是 2^31 - 1 ,所以权值是不是爆 int 了-- O( nlog ...
最新文章
- python中引用上层路径
- 【深度总结】聊聊为什么技术要先广后精,对技术新人的几点建议
- 指标搭建篇:如何搭建指标体系?——以公众号实战为例
- 【Python】Python实战从入门到精通之五 -- 教你使用文件写入
- Derby与mysql的关系_Derby数据库简单介绍和使用方法 | 学步园
- AutoCAD 2022 for Mac v2022.2.1中文版
- Function语意学之Member的各种调用方式
- 基于51单片机简易计算器LCD1602显示
- javasocket编程例子,给大家安排上!
- jquery ajax提交form表单,jquery+ajax提交form表单方法总结
- mac下打开.mpp后缀文件的工具OmniPlan
- 云计算之云计算和虚拟化的区别
- TCP/IP协议漏洞实验
- 创客教育的起源和内涵的基本理念
- python dataframe删除重复行_2.3.10 DataFrame 查看删除重复项
- 汇编指令学习(CMP,TEST)
- 【TouchDesigner】Feedback的应用NO.3
- 离人工智能进入我们的社会还有多远?(CES 2022 新品尝鲜)
- tenda服务器端口映射,腾达(Tenda)路由器端口映射设置教程 | 192路由网
- thinkphp6 短信宝/腾讯云发送手机号验证码
热门文章
- 【CodeForces - 1082B】Vova and Trophies (贪心模拟,暴力)
- oracle 1天后,Oracle Code One - 第1天 精彩亮点回顾
- spss相关性分析看结果_spss相关性分析
- 获取该字符串第N次出现的位置
- 管道实现父子进程的信息传递(二)【标准流和其文件描述符、fwrite函数、perror函数】
- LeetCode——二叉树序列化与反序列化
- 关系数据库——mysql常用函数总结
- python学习实例(5)
- Pytorch(5)-梯度反向传播
- 《Python Cookbook 3rd》笔记(3.2):执行精确的浮点数运算