[题解]:

#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. Android编程的写法规范

    一.获取View对象 1.private EditText m_txtSmsPhone = null;//定义一个EditText控件的调用对象 m_表示为View对象 txt表示文本框 2.在pro ...

  2. Android成长之路-手势识别的实现

      手势识别系统: 先把手势库放到项目中:(创建手势库见下一篇博客) 在res文件夹下新建一个名为raw的文件夹,然后把手势库放进去 然后开始项目的创建: strings.xml: <?xml  ...

  3. 不止是联网!教你玩转PC自带Wi-Fi网卡

    前言:Wi-Fi对于现在的智能手机来说已经是再熟悉不过的配置了,而主板自带Wi-Fi网卡的设计也越来越普及,但有些玩家可能思维还停留在“Wi-Fi网卡 = 连无线网络用的网卡,我用有线就不需要”的层次 ...

  4. npm stripts 使用指南

    Node 开发离不开 npm,而脚本功能是 npm 最强大.最常用的功能之一. 本文介绍如何使用 npm 脚本(npm scripts). 一.什么是 npm 脚本? npm 允许在package.j ...

  5. laravel多条件查询,及分页

    $res = DtkModel::where('ID','>','1')->select("ID")->get()->paginate(20);//不成立 ...

  6. Machine Learning—The k-means clustering algorithm

    印象笔记同步分享:Machine Learning-The k-means clustering algorithm

  7. 【ActiveMQ】ActiveMQ在Windows的安装,以及点对点的消息发送案例

    公司最近会用MQ对某些业务进行处理,所以,这次我下载了apache-activemq-5.12.0-bin把玩下. 基于练习方便需要,使用Windows的版本. 参考的优秀文章: activemq的几 ...

  8. jquery文件导入问题

    开发前台web,导入jquery文件的时候最好用 <script type="text/javascript" src="path"></sc ...

  9. springJDBC实现查询

    其实在Spring这个框架中,提供了一些对JDBC访问数据库的封装,其中JdbcTemplate就是一个很好用的类,下面来 演示一下这个类的一些用法.首先需要导入commons-logging.jar ...

  10. 示例 - 如何在NodeJS中调用SS生成的DLL

    要想在NodeJS中调用SS生成的DLL, 需要借助EdgeJS. EdgeJS: http://tjanczuk.github.io/edge/ 如果你还不知道如何在SS中生成DLL, 请查看: S ...