[题解]:

#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]树点染色的更多相关文章

  1. SDOI2017 树点染色

    \[SDOI2017 树点染色\] 题目描述 Bob 有一棵 $ n $ 个点的有根树,其中 $ 1 $ 号点是根节点.Bob 在每个节点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是,这 ...

  2. loj2001[SDOI2017]树点染色

    题意:给你一棵树,一开始每个点上的颜色互不相同.三种操作:op1:x到根的路径上的点都染上一种新的颜色.op2:设一条路径的权值为val(x,y),求x到y路径的val.op3:询问x的子树中最大的到 ...

  3. SDOI2017树点染色

    题目链接 发现1操作很像lct中的access,然后它每次染的又是一个新颜色,因此同一个颜色就在同一颗splay里了,且一个点到根的权值val[i]也就是到根路径上虚边的个数,然后看access时会对 ...

  4. 洛谷3703 [SDOI2017] 树点染色 【LCT】【线段树】

    题目分析: 操作一很明显等价于LCT上的access操作,操作二是常识,操作三转化到dfs序上求最大值也是常识.access的时候顺便在线段树中把对应部分-1,把右子树的子树+1即可. 代码: #in ...

  5. codevs 1191 树轴染色 线段树区间定值,求和

    codevs 1191 树轴染色 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1191/ Des ...

  6. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  7. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  8. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

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

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

随机推荐

  1. C#四舍五入保留一位小数

    DateTime d1 = hrStaff.DateJoin; DateTime d2 = DateTime.Now; TimeSpan d3 = d2.Subtract(d1); ; //int i ...

  2. 有道翻译 / 百度翻译Api

    比较推荐使用百度翻译api 不推荐有道翻译,比较水. http://ai.youdao.com/docs/doc-trans-api.s#p02 http://ai.youdao.com/docs/d ...

  3. Sublime Text 使用指南 - 前端开发神器

    Sublime Text 前端开发的神器 Sublime Text是一个前端开发者必备的编辑器,大量的插件,完善的功能,优越的性能,有非常多的特色,给前端开发提供了一个完善的开发条件. 本文主要介绍的 ...

  4. cocos2dx 3.x 开发环境搭建

    1. 准备工作 (1)VS2012 (2)cocos2dx cn.cocos2d-x.org/download (3)python 新版本的cocos2dx 需要python编译 2. 安装软件 (1 ...

  5. 每日英语: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 ...

  6. js基本知识5

    1.1 复习 1. 按钮不可用 disabled = “disabled” || true 2. setTimeout 只执行一次 setInterval 执行很多次 3. 递归调用 : 函数自己调用 ...

  7. mysql实现topN top1

    有时会碰到一些需求,查询分组后的最大值,最小值所在的整行记录或者分组后的top n行的记录,像在hive中是有窗口函数的,可以通过它们来实现,但是MySQL没有这些函数,可通过下面的方法来实现 1.准 ...

  8. Linux动态库开发

    http://blog.csdn.net/qq_33850438/article/details/52014399 ### 导出符号------------------------------ 默认所 ...

  9. hadoop之mapreduce编程实例(系统日志初步清洗过滤处理)

    刚刚开始接触hadoop的时候,总觉得必须要先安装hadoop集群才能开始学习MR编程,其实并不用这样,当然如果你有条件有机器那最好是自己安装配置一个hadoop集群,这样你会更容易理解其工作原理.我 ...

  10. C# Dictionary 复制

    Dictionary<string, int> dictionary = new Dictionary<string, int>(); dictionary.Add(" ...