题意:

解:

发现我们每次染的都是不同的颜色,那么用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 树点涂色的更多相关文章

  1. P3703 [SDOI2017]树点涂色

    P3703 [SDOI2017]树点涂色 链接 分析: 首先对于询问,感觉是线段树维护dfs序,每个点记录到根的颜色个数.第二问差分,第三问区间取max. 那么考虑修改,每次将一个点的颜色变成和父节点 ...

  2. 【LG3703】[SDOI2017]树点涂色

    [LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...

  3. [Sdoi2017]树点涂色 [lct 线段树]

    [Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...

  4. 「SDOI2017」树点涂色 解题报告

    「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...

  5. 【BZOJ4817】树点涂色(LCT,线段树,树链剖分)

    [BZOJ4817]树点涂色(LCT,线段树,树链剖分) 题面 BZOJ Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义 ...

  6. [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status ...

  7. 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

    树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...

  8. 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树

    [BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...

  9. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 629  Solved: 371[Submit][Status ...

随机推荐

  1. python爬虫-1

    import resquests #import urllib.request from bs4 import BeautifulSoup from collections import Ordere ...

  2. element-ui 源码解析 一

    Button组件 button.vue <template> <button class="el-button" @click="handleClick ...

  3. 简单比较init-method,afterPropertiesSet和BeanPostProcessor

    一.简单介绍 1.init-method方法,初始化bean的时候执行,可以针对某个具体的bean进行配置.init-method需要在applicationContext.xml配置文档中bean的 ...

  4. sql 保留2位小数/换行

    2.176544保留两位小数 1.select Convert(decimal(18,2),2.176544)  结果:2.18 2.select Round(2.176544,2) 结果:2.180 ...

  5. python易混易乱(1)

    字典 基础操作 <1>keys my_dict = {"name":"zhangsan","age":18} res = my_ ...

  6. 如何调用layer.open打开的的iframe窗口中的JS

  7. 各个版本spring的jar包以及源码下载地址,目前最高版本到spring4.3.8,留存备用:

    http://maven.springframework.org/release/org/springframework/spring/

  8. mysql必须知道的

    https://blog.csdn.net/xlgen157387/article/details/73691848

  9. Vasya and a Tree CodeForces - 1076E(线段树+dfs)

    I - Vasya and a Tree CodeForces - 1076E 其实参考完别人的思路,写完程序交上去,还是没理解啥意思..昨晚再仔细想了想.终于弄明白了(有可能不对 题意是有一棵树n个 ...

  10. hibernate多对多映射文件的配置

    user.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate ...