BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树
同BZOJ3779。
SDOI出原题,还是弱化版的。
吃枣药丸
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define maxn 200005 int n,m,data[maxn]; namespace Tree{
int h[maxn],to[maxn],ne[maxn],f[maxn][21],en=0,dep[maxn];
int id[maxn],in[maxn],out[maxn],tot=0;
void add(int a,int b)
{to[en]=b;ne[en]=h[a];h[a]=en++;}
void dfs(int o)
{
in[o]=++tot; id[tot]=o;
for (int i=h[o];i>=0;i=ne[i])
if (to[i]!=f[o][0])
f[to[i]][0]=o,dep[to[i]]=dep[o]+1,dfs(to[i]);
out[o]=tot;
}
void init()
{
F(i,1,20)F(j,1,n)f[j][i]=f[f[j][i-1]][i-1];
F(i,1,n) data[in[i]]=dep[i];
// F(i,1,n) printf("%d ",id[i]); printf("\n");
// F(i,1,n) printf("%d ",data[i]);printf("\n");
}
int LCA(int a,int b)
{
if (dep[a]<dep[b]) swap(a,b);
int dist=dep[a]-dep[b];
D(i,20,0) if ((dist>>i)&1) a=f[a][i];
if (a==b) return a;
D(i,20,0) if (f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];
return f[b][0];
}
} namespace SegTree{
int mx[maxn<<3],tag[maxn<<3];
void update(int o)
{mx[o]=max(mx[o<<1],mx[o<<1|1]);}
void pushdown(int o)
{
if (tag[o]!=0)
{
tag[o<<1]+=tag[o];
tag[o<<1|1]+=tag[o];
mx[o<<1]+=tag[o];
mx[o<<1|1]+=tag[o];
tag[o]=0;
}
}
void build(int o,int l,int r)
{
if (l==r)
{
mx[o]=data[l];
tag[o]=0;
return ;
}
pushdown(o);
int mid=l+r>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
update(o);
}
void modify(int o,int l,int r,int L,int R,int f)
{
if (L<=l&&r<=R)
{
tag[o]+=f;
mx[o]+=f;
return;
}
pushdown(o);
int mid=l+r>>1;
if (R<=mid) return modify(o<<1,l,mid,L,R,f),update(o);
else if (L>mid) return modify(o<<1|1,mid+1,r,L,R,f),update(o);
else return modify(o<<1,l,mid,L,R,f),modify(o<<1|1,mid+1,r,L,R,f),update(o);
}
void add(int a,int f)
{if (!a) return ;modify(1,1,n,Tree::in[a],Tree::out[a],f);}
int querymx(int o,int l,int r,int L,int R)
{
if (L<=l&&r<=R) return mx[o];
pushdown(o);
int mid=l+r>>1;
if (R<=mid) return querymx(o<<1,l,mid,L,R);
else if (L>mid) return querymx(o<<1|1,mid+1,r,L,R);
else return max(querymx(o<<1,l,mid,L,R),querymx(o<<1|1,mid+1,r,L,R));
}
} namespace LCT{
int rev[maxn],fa[maxn],ch[maxn][2],sta[maxn],top=0;
bool isroot(int o)
{return ch[fa[o]][0]!=o&&ch[fa[o]][1]!=o;}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0; else l=1; r=l^1;
if (!isroot(y))
{
if (ch[z][0]==y) ch[z][0]=x;
else ch[z][1]=x;
}
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r]; ch[x][r]=y;
}
void pushdown(int x)
{
if (rev[x])
{
rev[x]^=1;
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
}
}
void splay(int x)
{
sta[top=1]=x;
for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i];
while(top) pushdown(sta[top--]); while (!isroot(x))
{
int y=fa[x];
if (!isroot(y))
{
int z=fa[y];
if (ch[z][0]==y^ch[y][0]==x) rot(x);
else rot(y);
}
rot(x);
}
}
int find(int x)
{
pushdown(x);
while (ch[x][0]) x=ch[x][0],pushdown(x);
return x;
}
void access(int x)
{
for (int t=0;x;t=x,x=fa[x])
{
splay(x);
SegTree::add(find(ch[x][1]),1);
ch[x][1]=t;
SegTree::add(find(ch[x][1]),-1);
}
}
} int opt,x,y; int main()
{
scanf("%d%d",&n,&m);
memset(Tree::h,-1,sizeof Tree::h);
F(i,2,n)
{
int a,b;
scanf("%d%d",&a,&b);
Tree::add(a,b);
Tree::add(b,a);
}
Tree::dep[1]=1;Tree::dfs(1);Tree::init();
F(i,1,n) LCT::fa[i]=Tree::f[i][0];
SegTree::build(1,1,n);
F(i,1,m)
{
scanf("%d",&opt);
// cout<<opt<<endl;
switch(opt)
{
case 1: scanf("%d",&x); LCT::access(x); break;
case 2:
scanf("%d%d",&x,&y);
printf("%d\n",SegTree::querymx(1,1,n,Tree::in[x],Tree::in[x])+SegTree::querymx(1,1,n,Tree::in[y],Tree::in[y])+1-2*SegTree::querymx(1,1,n,Tree::in[Tree::LCA(x,y)],Tree::in[Tree::LCA(x,y)])); break;
case 3: scanf("%d",&x); printf("%d\n",SegTree::querymx(1,1,n,Tree::in[x],Tree::out[x]));break;
}
}
}
BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树的更多相关文章
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成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 ...
- BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)
题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...
- [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]
题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...
- BZOJ4817[Sdoi2017]树点涂色——LCT+线段树
题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...
- bzoj4817 & loj2001 [Sdoi2017]树点涂色 LCT + 线段树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4817 https://loj.ac/problem/2001 题解 可以发现这个题就是 bzo ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ 4817: [Sdoi2017]树点涂色(lct+线段树)
传送门 解题思路 跟重组病毒这道题很像.只是有了一个询问\(2\)的操作,然后询问\(2\)的答案其实就是\(val[x]+val[y]-2*val[lca(x,y)]+1\)(画图理解).剩下的操作 ...
随机推荐
- hdparm - 获取/设置硬盘参数
总览 hdparm [ -a [扇区数] ] [ -A [0|1] ] [ -c [芯片组模式] ] [ -C ] [ -d [0|1] ] [ -f ] [ -g ] [ -i ] [ -k [0| ...
- Talent Show
6349: Talent Show 时间限制: 1 Sec 内存限制: 128 MB提交: 106 解决: 40[提交] [状态] [讨论版] [命题人:admin] 题目描述 Farmer Jo ...
- python_81_标准库_时间模块
''' 标准库: 1.time 时间的三种表示方法:a:时间戳(timestamp) b:格式化的时间字符串 c:元组(struct_time)共九个元素 time.struct_time(tm_ye ...
- overloading and overriding
What is the difference between method overloading and method overriding in Java? Differences between ...
- DROP OPERATOR CLASS - 删除一个操作符类
SYNOPSIS DROP OPERATOR CLASS name USING index_method [ CASCADE | RESTRICT ] DESCRIPTION 描述 DROP OPER ...
- J.U.C知识点梳理
java.util.concurrent : 提供了并发编程的解决方案 1.CAS 是java.util.concurrent.atomic包的基础 2.AQS是java.util.concurren ...
- ovs的学习
本来编辑好了的, 结果忘了保存, 坑爹,直接把人家的网址贴上来吧 http://blog.chinaunix.net/uid-20737871-id-4333314.html 昨天遇到一个问题(虚拟机 ...
- MarkdownPad 2 Pro 注册码
MarkdownPad 2 Pro 注册码 MarkdownPad 是 Windows 平台上一个功能完善的 Markdown 编辑器. 提供了语法高亮和方便的快捷键功能,给您最好的 Markdown ...
- [BZOJ] 4145: [AMPPZ2014]The Prices
设\(f[S][i]\)表示考虑到第\(i\)家店,已经买了集合\(S\)内的物品 一个朴素的想法是枚举子集转移 \[ f[S][i]=\min\{f[T][i-1]+cost[S\oplus T][ ...
- LVS-nat模式-原理介绍
集群,为解决某个特定问题将多台计算机组合起来形成的单个系统 lvs-nat: 本质是多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和PORT实现转发 lvs集群类 ...