codevs 5963 [SDOI2017]树点染色
[题解]:


#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e5+;
struct edge{int v,next;}e[N<<];int tot,head[N],cur[N];
int n,m,top,st[N<<];
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void add(int x,int y){
e[++tot].v=y;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].next=head[y];head[y]=tot;
}
int dfs_cnt,dfn[N],end[N],pos[N];
int fa[N],fat[N][],dep[N];
void dfs(){
memcpy(cur,head,sizeof head);
int x;st[++top]=;dep[]=;
while(top){
con:
x=st[top];
if(!dfn[x]) dfn[x]=++dfs_cnt;
for(int &i=cur[x];i;){
if(e[i].v==fa[x]){i=e[i].next;continue;}
fa[e[i].v]=x;
fat[e[i].v][]=x;
dep[e[i].v]=dep[x]+;
st[++top]=e[i].v;
i=e[i].next;
goto con;
}
end[x]=dfs_cnt; top--;
}
for(int i=;i<=n;i++) pos[dfn[i]]=i;
}
const int M=N<<;
int mx[M],tag[M];
#define lch k<<1
#define rch k<<1|1
void build(int k,int l,int r){
if(l==r){
mx[k]=dep[pos[l]];return ;
}
int mid=l+r>>;
build(lch,l,mid);
build(rch,mid+,r);
mx[k]=max(mx[lch],mx[rch]);
}
void pushdown(int k){
if(!tag[k]) return ;
mx[lch]+=tag[k];
mx[rch]+=tag[k];
tag[lch]+=tag[k];
tag[rch]+=tag[k];
tag[k]=;
}
void plusx(int k,int l,int r,int x,int y,int val){
if(l==x&&r==y){
mx[k]+=val;
tag[k]+=val;
return ;
}
pushdown(k);
int mid=l+r>>;
if(y<=mid) plusx(lch,l,mid,x,y,val);
else if(x>mid) plusx(rch,mid+,r,x,y,val);
else plusx(lch,l,mid,x,mid,val),plusx(rch,mid+,r,mid+,y,val);
mx[k]=max(mx[lch],mx[rch]);
}
int ask(int k,int l,int r,int p){
if(l==r) return mx[k];
pushdown(k);
int mid=l+r>>;
if(p<=mid) return ask(lch,l,mid,p);
else return ask(rch,mid+,r,p);
}
int query(int k,int l,int r,int x,int y){
if(l==x&&r==y) return mx[k];
pushdown(k);
int mid=l+r>>;
if(y<=mid) return query(lch,l,mid,x,y);
else if(x>mid) return query(rch,mid+,r,x,y);
else return max(query(lch,l,mid,x,mid),query(rch,mid+,r,mid+,y));
}
int siz[N],ch[N][];
bool isroot(int x){
return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(ch[y][]==x);r=l^;
if(!isroot(y)) ch[z][ch[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
}
void splay(int x){
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((ch[y][]==x)^(ch[z][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
int findmin(int x){
if(!x) return ;
for(;ch[x][];x=ch[x][]);
return x;
}
void access(int x){
for(int y=,z;x;y=x,x=fa[x]){
splay(x);
z=findmin(ch[x][]);
if(z) plusx(,,n,dfn[z],end[z],);
if(fa[x]){
z=findmin(x);
plusx(,,n,dfn[z],end[z],-);
}
ch[x][]=y;
}
}
int lca(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int t=dep[a]-dep[b];
for(int i=;i<=;i++){
if((<<i)&t){
a=fat[a][i];
}
}
if(a==b) return a;
for(int i=;~i;i--){
if(fat[a][i]!=fat[b][i]){
a=fat[a][i];
b=fat[b][i];
}
}
return fat[a][];
}
int main(){
n=read();m=read();
for(int i=,x,y;i<n;i++) x=read(),y=read(),add(x,y);
dfs();
build(,,n);
for(int j=;j<=;j++){
for(int i=;i<=n;i++){
fat[i][j]=fat[fat[i][j-]][j-];
}
}
for(int i=,opt,x,y,anc,ans;i<=m;i++){
opt=read();x=read();
if(opt==) access(x);
if(opt==){
y=read();
anc=lca(x,y);
ans=ask(,,n,dfn[x])+ask(,,n,dfn[y])-*ask(,,n,dfn[anc])+;
printf("%d\n",ans);
}
if(opt==) printf("%d\n",query(,,n,dfn[x],end[x]));
}
return ;
}
codevs 5963 [SDOI2017]树点染色的更多相关文章
- SDOI2017 树点染色
\[SDOI2017 树点染色\] 题目描述 Bob 有一棵 $ n $ 个点的有根树,其中 $ 1 $ 号点是根节点.Bob 在每个节点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是,这 ...
- loj2001[SDOI2017]树点染色
题意:给你一棵树,一开始每个点上的颜色互不相同.三种操作:op1:x到根的路径上的点都染上一种新的颜色.op2:设一条路径的权值为val(x,y),求x到y路径的val.op3:询问x的子树中最大的到 ...
- SDOI2017树点染色
题目链接 发现1操作很像lct中的access,然后它每次染的又是一个新颜色,因此同一个颜色就在同一颗splay里了,且一个点到根的权值val[i]也就是到根路径上虚边的个数,然后看access时会对 ...
- 洛谷3703 [SDOI2017] 树点染色 【LCT】【线段树】
题目分析: 操作一很明显等价于LCT上的access操作,操作二是常识,操作三转化到dfs序上求最大值也是常识.access的时候顺便在线段树中把对应部分-1,把右子树的子树+1即可. 代码: #in ...
- codevs 1191 树轴染色 线段树区间定值,求和
codevs 1191 树轴染色 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1191/ Des ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1080 线段树点修改
先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...
- codevs 1082 线段树区间求和
codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
随机推荐
- C#四舍五入保留一位小数
DateTime d1 = hrStaff.DateJoin; DateTime d2 = DateTime.Now; TimeSpan d3 = d2.Subtract(d1); ; //int i ...
- 有道翻译 / 百度翻译Api
比较推荐使用百度翻译api 不推荐有道翻译,比较水. http://ai.youdao.com/docs/doc-trans-api.s#p02 http://ai.youdao.com/docs/d ...
- Sublime Text 使用指南 - 前端开发神器
Sublime Text 前端开发的神器 Sublime Text是一个前端开发者必备的编辑器,大量的插件,完善的功能,优越的性能,有非常多的特色,给前端开发提供了一个完善的开发条件. 本文主要介绍的 ...
- cocos2dx 3.x 开发环境搭建
1. 准备工作 (1)VS2012 (2)cocos2dx cn.cocos2d-x.org/download (3)python 新版本的cocos2dx 需要python编译 2. 安装软件 (1 ...
- 每日英语:Asia Has World's Biggest Pay Gap, Study Finds
In Asia, middle managers such as department heads make more than 14 times as much as operational emp ...
- js基本知识5
1.1 复习 1. 按钮不可用 disabled = “disabled” || true 2. setTimeout 只执行一次 setInterval 执行很多次 3. 递归调用 : 函数自己调用 ...
- mysql实现topN top1
有时会碰到一些需求,查询分组后的最大值,最小值所在的整行记录或者分组后的top n行的记录,像在hive中是有窗口函数的,可以通过它们来实现,但是MySQL没有这些函数,可通过下面的方法来实现 1.准 ...
- Linux动态库开发
http://blog.csdn.net/qq_33850438/article/details/52014399 ### 导出符号------------------------------ 默认所 ...
- hadoop之mapreduce编程实例(系统日志初步清洗过滤处理)
刚刚开始接触hadoop的时候,总觉得必须要先安装hadoop集群才能开始学习MR编程,其实并不用这样,当然如果你有条件有机器那最好是自己安装配置一个hadoop集群,这样你会更容易理解其工作原理.我 ...
- C# Dictionary 复制
Dictionary<string, int> dictionary = new Dictionary<string, int>(); dictionary.Add(" ...


