题意:

解:

发现我们每次染的都是不同的颜色,那么用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. freemarker 简单操作

    操作字符串函数 1. substring(start,end)从一个字符串中截取子串 start:截取子串开始的索引,start必须大于等于0,小于等于end end: 截取子串的长度,end必须大于 ...

  2. GitHub创建仓库,并与git本地仓库关联

    登录后头像右上角点击: 起名再create 后 会跳转到下面页面: 先在git上复制执行第一条指令,创建一个readme文档 然后再用第二条初始化仓库 第三步将readme文档添加至暂存区 然后提交一 ...

  3. Yii2控制台程序最佳实践

    模板工程标准的控制台程序要素: (1)完整明确文字提示用户(并且使用红,绿,黄三种颜色标识提示文字:红色为错误相关,绿色为成功相关,黄色为进行中提示) (2)告知用户运行进度(完成任务的一部分即显示进 ...

  4. vue之v-for使用说明

    demo.html <!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/19 ...

  5. 【转】console.log 用法

    标签: 转自http://www.cnblogs.com/ctriphire/p/4116207.html 大家都有用过各种类型的浏览器,每种浏览器都有自己的特色,本人拙见,在我用过的浏览器当中,我是 ...

  6. jq的$.each()方法

    jq的$.each()方法: 语法:jQuery.each(object, [callback]) 回调函数拥有两个参数:第一个为对象的成员或数组的索引,第二个为对应变量或内容.如果需要退出 each ...

  7. 包packages

    packages里面如何跨模块导入路径: print(dir()) 可以看到__file__ print(os.path.abspaht(__file__)) 可以看到当前绝对路径 import sy ...

  8. 集成Javascript Logging on MVC or Core

    ASP.NET Core provides us a rich Logging APIs which have a set of logger providers including: Console ...

  9. servlet篇 之 servlet的访问

    三:servlet的访问 使用web.xml文件中的这个<url-pattern>标签中的映射路径,来访问servlet 6.1 在浏览器的地址栏中,直接输入servlet映射的路径来访问 ...

  10. Mysql(Mariadb)数据库主从复制

    Mysql主从复制的实现原理图大致如下: MySQL之间数据复制的基础是以二进制日志文件(binary log file)来实现的,一台MySQL数据库一旦启用二进制日志后,其作为master,它数据 ...