洛谷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 ...
随机推荐
- Notepad++ 安装 NppFTP 插件
How to install a plugin The plugin (in the DLL form) should be placed in the \plugins subfolder of t ...
- PLSQL 错误问题:ora-12154:TNS:could not resolve the connect identifier
错误问题: ORA-12154: TNS:could not resolve the connect identifier specified 即无法解析指定的连接,这说明缺少了一个环境变量,TNS_ ...
- Java之指定Junit测试方法的执行顺序举例
问题描述: 大家都知道使用JUnit进行测试的时候,方法的执行顺序不是按照编写的先后顺序执行的,那么如何控制Junit的执行顺序呢? 解决方法: 在测试类上加 @FixMethodOrder 注解即可 ...
- jedis单机版应用
1.pom文件添加依赖: 2.创建配置文件 创建单机版redisClient 代码: package com.skymall.rest.dao.imp; import org.springframew ...
- excel导入、导出
http://blog.csdn.net/cjh200102/article/details/12557599 NPOI 工作本HSSFWorkbook 构造方法,无参表示创建一个新的工作本,可以接收 ...
- 趣味网站5个,小鸡词典/中国配色/名著地图/海洋之音/LOGO设计
一.小鸡词典 很多流行的词语还没有收录到各大词典,却可以在小鸡词典搜索到,小鸡词典是最全的网络流行词语词典. 不少词条搞笑无厘头,撰写词条还会获得红包. 访问地址:https://jikipedia. ...
- 前端 -- CSS基础
一,CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). 二,CSS语法 1 ...
- Matplotlib学习---用matplotlib画热图(heatmap)
这里利用Nathan Yau所著的<鲜活的数据:数据可视化指南>一书中的数据,学习画图. 数据地址:http://datasets.flowingdata.com/ppg2008.csv ...
- 不同版本的Chrom浏览器对应的ChromDriver的版本
附chromedriver与chrome的对应关系表: chromedriver版本 支持的Chrome版本 v2.40 v66-68 v2.39 v66-68 v2.38 v65-67 v2.37 ...
- 如何让自己定义的memory使用fpga自带的memory资源
前言 本文解决方法来源: http://quartushelp.altera.com/13.1/mergedProjects/hdl/vlog/vlog_file_dir_ram.htm 如果你自己V ...