洛谷P3703 树点涂色
题意:
解:
发现我们每次染的都是不同的颜色,那么用lct维护的话一个颜色就会在一个splay里。染色是access。
维护每个节点到根路径上的虚边数量。
虚边的切换只会在access和link中出现。于是access的时候顺便修改那个子树。lct上啥也不用维护。
查询链可以用两端点减去lca。
#include <bits/stdc++.h>
const int N = , INF = 0x3f3f3f3f;
struct Edge {
int nex, v;
}edge[N << ]; int tp;
int e[N], n, siz[N], pos[N], id[N], d[N], num, top[N], father[N], son[N]; /// tree
int fa[N], s[N][], stk[N], Top; /// lct
bool rev[N];
int large[N << ], tag[N << ]; /// seg
inline void add(int x, int y) {
tp++;
edge[tp].v = y;
edge[tp].nex = e[x];
e[x] = tp;
return;
}
void DFS_1(int x, int f) { /// father siz son d
siz[x] = ;
fa[x] = father[x] = f;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f) continue;
d[y] = d[x] + ;
DFS_1(y, x);
siz[x] += siz[y];
if(siz[y] > siz[son[x]]) {
son[x] = y;
}
}
return;
}
void DFS_2(int x, int f) { /// top id pos
top[x] = f;
pos[x] = ++num;
id[num] = x;
if(son[x]) DFS_2(son[x], f);
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == father[x] || y == son[x]) continue;
DFS_2(y, y);
}
return;
}
inline void Pushdown(int o) {
if(tag[o]) {
int ls = o << , rs = o << | ;
tag[ls] += tag[o];
tag[rs] += tag[o];
large[ls] += tag[o];
large[rs] += tag[o];
tag[o] = ;
}
return;
}
void build(int l, int r, int o) {
if(l == r) {
large[o] = d[id[r]];
return;
}
int mid = (l + r) >> ;
build(l, mid, o << );
build(mid + , r, o << | );
large[o] = std::max(large[o << ], large[o << | ]);
return;
}
void add(int L, int R, int v, int l, int r, int o) {
if(L <= l && r <= R) {
large[o] += v;
tag[o] += v;
return;
}
Pushdown(o);
int mid = (l + r) >> ;
if(L <= mid) add(L, R, v, l, mid, o << );
if(mid < R) add(L, R, v, mid + , r, o << | );
large[o] = std::max(large[o << ], large[o << | ]);
return;
}
int getMax(int L, int R, int l, int r, int o) {
if(L <= l && r <= R) return large[o];
int mid = (l + r) >> , ans = -INF;
Pushdown(o);
if(L <= mid) ans = std::max(ans, getMax(L, R, l, mid, o << ));
if(mid < R) ans = std::max(ans, getMax(L, R, mid + , r, o << | ));
return ans;
}
int ask(int p, int l, int r, int o) {
if(l == r) return large[o];
Pushdown(o);
int mid = (l + r) >> ;
if(p <= mid) return ask(p, l, mid, o << );
else return ask(p, mid + , r, o << | );
}
inline void pushdown(int x) {
if(rev[x]) {
std::swap(s[x][], s[x][]);
if(s[x][]) rev[s[x][]] ^= ;
if(s[x][]) rev[s[x][]] ^= ;
rev[x] = ;
}
return;
}
inline void pushup(int x) {
return;
}
inline bool no_root(int x) {
return (s[fa[x]][] == x) || (s[fa[x]][] == x);
}
inline void rotate(int x) {
int y = fa[x];
int z = fa[y];
bool f = (s[y][] == x);
fa[x] = z;
if(no_root(y)) {
s[z][s[z][] == y] = x;
}
s[y][f] = s[x][!f];
if(s[x][!f]) {
fa[s[x][!f]] = y;
}
s[x][!f] = y;
fa[y] = x;
pushup(y);
return;
}
inline void splay(int x) {
int y = x;
stk[++Top] = y;
while(no_root(y)) {
y = fa[y];
stk[++Top] = y;
}
while(Top) {
pushdown(stk[Top]);
Top--;
}
y = fa[x];
int z = fa[y];
while(no_root(x)) {
if(no_root(y)) {
(s[z][] == y) ^ (s[y][] == x) ?
rotate(x) : rotate(y);
}
rotate(x);
y = fa[x];
z = fa[y];
}
pushup(x);
return;
}
inline void change(int x, int v) {
pushdown(x);
while(s[x][]) {
x = s[x][];
pushdown(x);
}
/// x
add(pos[x], pos[x] + siz[x] - , v, , n, );
return;
}
inline void access(int x) {
int y = ;
while(x) {
splay(x);
if(s[x][]) change(s[x][], );
if(y) change(y, -);
s[x][] = y;
pushup(x);
y = x;
x = fa[x];
}
return;
}
inline int lca(int x, int y) {
while(top[x] != top[y]) {
if(d[top[x]] < d[top[y]]) {
y = father[top[y]];
}
else {
x = father[top[x]];
}
}
return d[x] < d[y] ? x : y;
}
inline int ask(int x, int y) {
//printf("ask : %d %d lca %d \n", x, y, lca(x, y));
//printf("ask : %d + %d - 2 * %d \n", ask(pos[x], 1, n, 1), ask(pos[y], 1, n, 1), ask(pos[lca(x, y)], 1, n, 1));
return ask(pos[x], , n, ) + ask(pos[y], , n, ) - * ask(pos[lca(x, y)], , n, );
}
inline int query(int x) {
return getMax(pos[x], pos[x] + siz[x] - , , n, );
}
int main() {
int m;
scanf("%d%d", &n, &m);
for(int i = , x, y; i < n; i++) {
scanf("%d%d", &x, &y);
add(x, y); add(y, x);
}
/// init
DFS_1(, );
DFS_2(, );
build(, n, );
for(int i = , f, x, y; i <= m; i++) {
scanf("%d%d", &f, &x);
if(f == ) { /// change
access(x);
}
else if(f == ) {
scanf("%d", &y);
printf("%d\n", ask(x, y) + );
}
else { /// f == 3
printf("%d\n", query(x) + );
}
}
return ;
}
AC代码
洛谷P3703 树点涂色的更多相关文章
- P3703 [SDOI2017]树点涂色
P3703 [SDOI2017]树点涂色 链接 分析: 首先对于询问,感觉是线段树维护dfs序,每个点记录到根的颜色个数.第二问差分,第三问区间取max. 那么考虑修改,每次将一个点的颜色变成和父节点 ...
- 【LG3703】[SDOI2017]树点涂色
[LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
- 「SDOI2017」树点涂色 解题报告
「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...
- 【BZOJ4817】树点涂色(LCT,线段树,树链剖分)
[BZOJ4817]树点涂色(LCT,线段树,树链剖分) 题面 BZOJ Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义 ...
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 692 Solved: 408[Submit][Status ...
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...
- 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树
[BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...
- [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 629 Solved: 371[Submit][Status ...
随机推荐
- Flutter常用插件
Dio Dio是一个强大的Dart Http请求库,支持Restful API.FormData.拦截器.请求取消等操作.视频中将全面学习和使用Dio的操作. Flutter_swiper swipe ...
- python数据结构与算法第七天【链表】
1.链表的定义 如图: 注意: (1)线性表包括顺序表和链表 (2)顺序表是将元素顺序地存放在一块连续的存储区里 (3)链表是将元素存放在通过链构造的存储快中 2. 单向链表的实现 #!/usr/bi ...
- Bootstrap之登陆页面范例
代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta ...
- Spring4 MVC Hibernate4 maven集成
http://www.cnblogs.com/leiOOlei/p/3727859.html
- How to helloworld on Xcode
create a mac app,click button to change label text? create project,click left window button on Main. ...
- webpack始出来
一直想好好整理一下webpack,现在就整理吧. 总结自己的实际搭建的整理情况,我还是要先对自己说一句,以后给文件夹起名字的时候不要用一些特殊的关键字,比如我在做这个demo的时候,我用的文件夹名称叫 ...
- navicat激活
参考:https://www.jianshu.com/p/5f693b4c9468 一开始想激活12.1.8,但是激活按钮一直点不了,换了个12.0激活成功
- BZOJ 3514: Codechef MARCH14 GERALD07加强版(LCT + 主席树)
题意 \(N\) 个点 \(M\) 条边的无向图,询问保留图中编号在 \([l,r]\) 的边的时候图中的联通块个数. \(K\) 次询问强制在线. \(1\le N,M,K \le 200,000\ ...
- Leetcode 167. 两数之和 II - 输入有序数组 By Python
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的下标值 ...
- Java简单工厂模式(SimpleFactoryMode)
何为简单工厂模式? 由一个工厂类根据传入的参数,动态创建并返回相应的具体的实例! 三个构成元素: 1.工厂类 2.抽象产品 3.具体产品 优点: 1.提高扩展性 2.隐藏具体的实现类,并不需要知道产品 ...