BZOJ4817[Sdoi2017]树点涂色——LCT+线段树
题目描述
输入
输出
样例输入
1 2
2 3
3 4
3 5
2 4 5
3 3
1 4
2 4 5
1 5
2 4 5
样例输出
4
2
2
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int c[100010][2];
int fa[100010];
int tag[400010];
int f[100010][18];
int dep[100010];
int mx[400010];
int dfn;
int tot;
int x,y;
int n,m;
int opt;
int head[100010];
int next[200010];
int to[200010];
int q[100010];
int s[100010];
int t[100010];
void add(int x,int y)
{
next[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void pushup(int rt)
{
mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void pushdown(int rt)
{
if(tag[rt])
{
tag[rt<<1]+=tag[rt];
tag[rt<<1|1]+=tag[rt];
mx[rt<<1]+=tag[rt];
mx[rt<<1|1]+=tag[rt];
tag[rt]=0;
}
}
void build(int rt,int l,int r)
{
if(l==r)
{
mx[rt]=dep[q[l]];
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void change(int rt,int l,int r,int L,int R,int v)
{
if(L<=l&&r<=R)
{
tag[rt]+=v;
mx[rt]+=v;
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid)
{
change(rt<<1,l,mid,L,R,v);
}
if(R>mid)
{
change(rt<<1|1,mid+1,r,L,R,v);
}
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return mx[rt];
}
pushdown(rt);
int mid=(l+r)>>1;
int res=0;
if(L<=mid)
{
res=max(res,query(rt<<1,l,mid,L,R));
}
if(R>mid)
{
res=max(res,query(rt<<1|1,mid+1,r,L,R));
}
return res;
}
int ask(int rt,int l,int r,int k)
{
if(l==r)
{
return mx[rt];
}
pushdown(rt);
int mid=(l+r)>>1;
if(k<=mid)
{
return ask(rt<<1,l,mid,k);
}
else
{
return ask(rt<<1|1,mid+1,r,k);
}
}
bool is_root(int rt)
{
return rt!=c[fa[rt]][0]&&rt!=c[fa[rt]][1];
}
bool get(int rt)
{
return rt==c[fa[rt]][1];
}
void rotate(int rt)
{
int x=fa[rt];
int y=fa[x];
int k=get(rt);
if(!is_root(x))
{
c[y][get(x)]=rt;
}
c[x][k]=c[rt][k^1];
fa[c[rt][k^1]]=x;
c[rt][k^1]=x;
fa[x]=rt;
fa[rt]=y;
}
void splay(int rt)
{
for(int x;!is_root(rt);rotate(rt))
{
if(!is_root(x=fa[rt]))
{
rotate(get(x)==get(rt)?x:rt);
}
}
}
void link(int x,int y)
{
fa[x]=y;
}
int find(int rt)
{
while(c[rt][0])
{
rt=c[rt][0];
}
return rt;
}
void access(int rt)
{
for(int x=0;rt;x=rt,rt=fa[rt])
{
splay(rt);
if(x)
{
int son=find(x);
change(1,1,n,s[son],t[son],-1);
}
if(c[rt][1])
{
int son=find(c[rt][1]);
change(1,1,n,s[son],t[son],1);
}
c[rt][1]=x;
}
}
void dfs(int x)
{
s[x]=++dfn;
q[dfn]=x;
for(int i=1;i<=17;i++)
{
f[x][i]=f[f[x][i-1]][i-1];
}
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x][0])
{
f[to[i]][0]=x;
link(to[i],x);
dep[to[i]]=dep[x]+1;
dfs(to[i]);
}
}
t[x]=dfn;
}
int lca(int x,int y)
{
if(dep[x]<dep[y])
{
swap(x,y);
}
int d=dep[x]-dep[y];
for(int i=0;i<=17;i++)
{
if(d&(1<<i))
{
x=f[x][i];
}
}
if(x==y)
{
return x;
}
for(int i=17;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dep[1]=1;
dfs(1);
build(1,1,n);
while(m--)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d",&x);
access(x);
}
else if(opt==2)
{
scanf("%d%d",&x,&y);
int anc=lca(x,y);
int ans=ask(1,1,n,s[x])+ask(1,1,n,s[y])-2*ask(1,1,n,s[anc])+1;
printf("%d\n",ans);
}
else
{
scanf("%d",&x);
printf("%d\n",query(1,1,n,s[x],t[x]));
}
}
}
BZOJ4817[Sdoi2017]树点涂色——LCT+线段树的更多相关文章
- 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树
[BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
- [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]
题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...
- bzoj4817 & loj2001 [Sdoi2017]树点涂色 LCT + 线段树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4817 https://loj.ac/problem/2001 题解 可以发现这个题就是 bzo ...
- BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)
题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树
同BZOJ3779. SDOI出原题,还是弱化版的. 吃枣药丸 #include <map> #include <cmath> #include <queue> # ...
- BZOJ 4817: [Sdoi2017]树点涂色(lct+线段树)
传送门 解题思路 跟重组病毒这道题很像.只是有了一个询问\(2\)的操作,然后询问\(2\)的答案其实就是\(val[x]+val[y]-2*val[lca(x,y)]+1\)(画图理解).剩下的操作 ...
随机推荐
- openlayers3 实现点选的几种方式
WebGIS开发中,点击查询是最常用的一种查询方式,在ArcGIS api 中,这种查询叫IdentifyTask,主要作用是前台提交参数,交ArcServer查询分析返回.本文从开源框架的角度,从前 ...
- 从.Net到Java学习第四篇——spring boot+redis
从.Net到Java学习系列目录 “学习java已经十天,有时也怀念当初.net的经典,让这语言将你我相连,怀念你......”接上一篇,本篇使用到的框架redis.FastJSON. 环境准备 安装 ...
- C#监控指定目录的文件变化的代码
如下的资料是关于C#监控指定目录的文件变化的代码. FileSystemWatcher watcher = new FileSystemWatcher();watcher.Path = @" ...
- 微信小程序控件 横/纵向排列
控件(按钮)横向排列 wxss .view_class { display: flex; flex-direction: row; justify-content: center; } 控件(按钮)纵 ...
- QT使用websocket进行长连接
一般我们用的最多的就是http请求,但是频繁的请求可能对服务造成的压力很大,所以今天谈谈websocket长连接,一句话:简单 1.什么是长连接? A:一次请求连接,终身使用,就可以长久的保持信息的交 ...
- Asp.Net Core 实现服务的批量注册注入
- MongoDB在Linux系统下的安装与启动
Mongodb介绍 MongoDB是一个开源文档数据库,提供高性能,高可用性和自动扩展,官方文档:https://docs.mongodb.com/manual/introduction/ Mongo ...
- 聚类——GMM
聚类——认识GMM算法 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 一.GMM概述 二.GMM算法步骤 三.具体推导参考文献 1. 李航. 统计学习 ...
- 【English】20190313
indicators指针['ɪndɪkeɪtəz] determine决定[dɪˈtɜ:rmɪn] Places null indicator bits at the front of each ...
- 【Teradata Utility】使用SQL Assistant导出导入数据
1.导出 (1)选择菜单栏File,点击Export Results,输入导出数据的SQL: select * from etl_data.soure_table; (2)选择导出数据格式为txt或h ...