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的形式! 如何求颜色数? ...
随机推荐
- 【iOS开发-25】UIDevice查看系统信息,从一个问题開始怎样高速找到自己想要的属性和方法并看懂它
如果须要解决的问题:写代码时遇到一种情况,就是须要推断iOS版本号,可能低版本号和高版本号须要增减一些代码,此时.怎样推断iOS版本号? (1)第一步.当然度娘.输入"iOS 推断系统版本号 ...
- Dbvisual连接远程数据库报错Error Code: 17401
Long Message:违反协议 Details: Type: java.sql.SQLException Error Code: 17401 SQL State: null 现象: 本 ...
- queue for max elem, pop, push
queue for max elem, pop, push 个人信息:就读于燕大本科软件project专业 眼下大三; 本人博客:google搜索"cqs_2012"就可以; 个人 ...
- centos IPTables 配置方法
entos IPTables 配置方法 http://os.51cto.com/art/201103/249359_1.htm iptables 指南 1.1.19 http://www.frozen ...
- js代码中定义后台java中的上下文路径
var href = <c:out value='${sessionScope.contextPath}' />
- c#第一个程序-计算平方根
上课教的内容.做笔记了. using System; using System.Collections.Generic; using System.ComponentModel; using Syst ...
- HashMap原理<转>
1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1 ...
- git 删除分之以及删除文件夹
1.删除分支 1.1查看所有分支: git branch -a 得到结果: 1.2删除HEAD分支 git push origin --delete HEAD 2.删除文件夹 2.1 查看本地分支下的 ...
- 011杰信-创建购销合同Excel报表系列-4-建立合同货物(修改,删除):合同货物表是购销合同表的子表
前面的一篇文章做的是修改删除,这篇文章做的是合同货物的修改和删除. 业务功能如下:
- import是page指令的一个属性。
以下不属于JSP的标准指令的是.(选择1项) A.Taglib B.Include C.Import D.Page 解答:C


