loj2001 「SDOI2017」树点涂色
#include <iostream>
#include <cstdio>
using namespace std;
int n, m, dfn[100005], idx, hea[100005], cnt, uu, vv, siz[100005], fa[100005][19];
int dep[100005], val[400005], dui[100005], opt, ch[100005][2], tag[400005];
int af[100005];
struct Edge{
int too, nxt;
}edge[200005];
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
bool isRoot(int x){
return ch[af[x]][0]!=x && ch[af[x]][1]!=x;
}
bool getW(int x){
return ch[af[x]][1]==x;
}
void dfs(int x, int f){
fa[x][0] = f;
af[x] = f;
dep[x] = dep[f] + 1;
dfn[x] = ++idx;
dui[idx] = dep[x];
siz[x] = 1;
for(int i=1; i<=16; i++)
fa[x][i] = fa[fa[x][i-1]][i-1];
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=f){
dfs(t, x);
siz[x] += siz[t];
}
}
}
void build(int o, int l, int r){
if(l==r) val[o] = dui[l];
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
if(l<=mid) build(lson, l, mid);
if(mid<r) build(rson, mid+1, r);
val[o] = max(val[lson], val[rson]);
}
}
void rotate(int x){
int old=af[x], oldf=af[old], w=getW(x);
if(!isRoot(old)) ch[oldf][ch[oldf][1]==old] = x;
ch[old][w] = ch[x][w^1]; ch[x][w^1] = old;
af[ch[old][w]] = old; af[ch[x][w^1]] = x; af[x] = oldf;
}
void splay(int x){
while(!isRoot(x)){
int f=af[x];
if(!isRoot(f)) rotate(getW(f)==getW(x)?f:x);
rotate(x);
}
}
int findRoot2(int x){
while(ch[x][0]) x = ch[x][0];
return x;
}
void sgtPushDown(int o, int l, int r, int lson, int rson, int mid){
val[lson] += tag[o];
val[rson] += tag[o];
tag[lson] += tag[o];
tag[rson] += tag[o];
tag[o] = 0;
}
void update(int o, int l, int r, int x, int y, int k){
if(l>=x && r<=y){
val[o] += k;
tag[o] += k;
}
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
if(tag[o]) sgtPushDown(o, l, r, lson, rson, mid);
if(x<=mid) update(lson, l, mid, x, y, k);
if(mid<y) update(rson, mid+1, r, x, y, k);
val[o] = max(val[lson], val[rson]);
}
}
void access(int x){
int y=0;
while(x){
splay(x);
if(ch[x][1]){
int t=findRoot2(ch[x][1]);
update(1, 1, n, dfn[t], dfn[t]+siz[t]-1, 1);
}
ch[x][1] = y;
if(ch[x][1]){
int t=findRoot2(ch[x][1]);
update(1, 1, n, dfn[t], dfn[t]+siz[t]-1, -1);
}
y = x;
x = af[x];
}
}
int getLca(int u, int v){
if(dep[u]<dep[v]) swap(u, v);
for(int i=16; i>=0; i--)
if(dep[fa[u][i]]>=dep[v])
u = fa[u][i];
if(u==v) return u;
for(int i=16; i>=0; i--)
if(fa[u][i]!=fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
int query(int o, int l, int r, int x, int y){
if(l>=x && r<=y) return val[o];
else{
int mid=(l+r)>>1;
int lson=o<<1;
int rson=lson|1;
int ans=0;
if(tag[o]) sgtPushDown(o, l, r, lson, rson, mid);
if(x<=mid) ans = max(ans, query(lson, l, mid, x, y));
if(mid<y) ans = max(ans, query(rson, mid+1, r, x, y));
return ans;
}
}
int main(){
cin>>n>>m;
for(int i=1; i<n; i++){
scanf("%d %d", &uu, &vv);
add_edge(uu, vv);
add_edge(vv, uu);
}
dfs(1, 0);
build(1, 1, n);
while(m--){
scanf("%d", &opt);
if(opt==1){
scanf("%d", &uu);
access(uu);
}
else if(opt==2){
scanf("%d %d", &uu, &vv);
int lca=getLca(uu, vv);
printf("%d\n", query(1, 1, n, dfn[uu], dfn[uu])+query(1, 1, n, dfn[vv], dfn[vv])-2*query(1, 1, n, dfn[lca], dfn[lca])+1);
}
else{
scanf("%d", &uu);
printf("%d\n", query(1, 1, n, dfn[uu], dfn[uu]+siz[uu]-1));
}
}
return 0;
}
loj2001 「SDOI2017」树点涂色的更多相关文章
- 「SDOI2017」树点涂色 解题报告
「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...
- [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]
题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
- P3703 [SDOI2017]树点涂色
P3703 [SDOI2017]树点涂色 链接 分析: 首先对于询问,感觉是线段树维护dfs序,每个点记录到根的颜色个数.第二问差分,第三问区间取max. 那么考虑修改,每次将一个点的颜色变成和父节点 ...
- 【LG3703】[SDOI2017]树点涂色
[LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 692 Solved: 408[Submit][Status ...
- 【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 ...
随机推荐
- Java基础语法(自定义类、ArrayList集合)
Java基础语法 今日内容介绍 u 自定义类 u ArrayList集合 第1章 引用数据类型(类) 1.1 引用数据类型分类 提到引用数据类型(类),其实我们对它并不陌生,如使用过的Scanner类 ...
- ABAP数据类型
数据类型表: 类型缩写 类型 默认长度 允许长度 初始值 描述 C 文本型 1 Space 字符串数据,如'Program' D 日期型 8 8 '00000000' 日期数据,格式为YYYYMM ...
- nmap -sS
SYN 扫描,半连接,受到syn/ack响应后意味着端口开放,收到rst包意味着端口关闭.
- 深入理解Java流机制(一)
一.前言 C语言本身没有输入输出语句,而是调用"stdio.h"库中的输入输出函数来实现.同样,C++语言本身也没有输入输出,不过有别于C语言,C++有一个面向对象的I/O流类库& ...
- 本号讯 | 人工智能手表为帕金森患者带来书写希望;微软翻译发布可实时翻译幻灯片的Presentation Translator
7 月 12 日,微软成立微软研究院人工智能中心(Microsoft Research AI).这是一个隶属于微软研究体系内的科研和孵化中心,将聚焦于解决最复杂的人工智能挑战. 这支由科学家和工程师组 ...
- Android(java)学习笔记108:Android的Junit调试
1. Android的Junit调试: 编写android应用的时候,往往我们需要编写一些业务逻辑实现类,但是我们可能不能明确这个业务逻辑是否可以成功实现,特别是逻辑代码体十分巨大的时候,我们不可能一 ...
- JS函数的length属性
length 是函数对象的一个属性值,指该函数有多少个必须要传入的参数,那些已定义了默认值的参数不算在内,比如function(xx = 0)的length是0.. 另外在函数内部:arguments ...
- stixel 理解
在车辆所处平面建立极坐标占位网格(polar occupancy grid),将视差图所代表的三维世界(3D world) 正交投影到该平面中. occupancy:每个网格被赋予一个占位数,代表了该 ...
- IDE spec for registry settings
IDE spec for registry settings Advanced customization of Visual Assist is possible with registry set ...
- JavaScript深入浅出第2课:函数是一等公民是什么意思呢?
摘要: 听起来很炫酷的一等公民是啥? <JavaScript深入浅出>系列: JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼? JavaScript深入浅出第2课:函 ...