[Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)
4817: [Sdoi2017]树点涂色
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 629 Solved: 371
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
题解:
其实这道题考的十分妙啊,对LCT的虚实边性质进行了充分的利用。
当lca和其中一个相同时,我们发现还是减多了,还是得加回来。
一条链的情况自己画图也是同理的。这样对于操作2就用线段树轻松维护了。
操作3????不就是线段树dfs序查询子树吗。
这样我们就神奇的利用了LCT的性质把一道看似树剖的题做成了LCT神题。。
AC代码:
过了样例直接交,一遍交过的酸爽
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
const int N = 2e5 + ;
int st[N],ed[N],fa[N],ch[N][],s[N << ],la[N << ],n,m,head[N],dt;
struct Edge{
int to,nex;
}edge[N << ];
void AddEdge(int u,int v)
{
edge[++dt] = (Edge){v,head[u]};
head[u] = dt;
}
bool isroot(int x){return ch[fa[x]][] != x && ch[fa[x]][] != x;}
void rotate(int x,int d)
{
int pre = fa[x],g = fa[pre],nex = ch[x][d];
ch[pre][d ^ ] = nex;
if(nex)fa[nex] = pre;
fa[x] = g;
if(!isroot(pre))ch[g][ch[g][] == pre] = x;
ch[x][d] = pre;
fa[pre] = x;
}
void splay(int x)
{
int pre,g;
while(!isroot(x))
{
pre = fa[x],g = fa[pre];
if(!isroot(pre) && !((ch[pre][] == x) ^ (ch[g][] == pre)))rotate(pre,ch[pre][] == x);
rotate(x,ch[pre][] == x);
}
}
int find(int x){while(ch[x][])x = ch[x][];return x;}
void push(int x){s[x] = max(s[x << ],s[x << | ]);}
void down(int x)
{
s[x << ] += la[x];s[x << | ] += la[x];
la[x << | ] += la[x];la[x << ] += la[x];
la[x] = ;
}
void updata(int L,int R,int l,int r,int rt,int d)
{
if(L <= l && r <= R){s[rt] += d;la[rt] += d;return;}
down(rt);int mid = l + r >> ;
if(L <= mid)updata(L,R,l,mid,rt << ,d);
if(R > mid)updata(L,R,mid + ,r,rt << | ,d);
push(rt);
}
int Query(int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R)return s[rt];
down(rt);int mid = l + r >> ;
if(L > mid)return Query(L,R,mid + ,r,rt << | );
if(R <= mid)return Query(L,R,l,mid,rt << );
return max(Query(L,R,l,mid,rt << ),Query(L,R,mid + ,r,rt << | ));
}
int ask(int x){return Query(st[x],st[x],,n,);}
void access(int x)
{
int y = ,t;
while(x)
{
splay(x);
if(t = find(ch[x][]))updata(st[t],ed[t],,n,,);
ch[x][] = y;if(t = find(y))updata(st[t],ed[t],,n,,-);
y = x;x = fa[x];
}
}
int hson[N],sz[N],tot,top[N],dep[N],Fa[N],id[N];
void dfs(int u)
{
sz[u] = ;
for(int i = head[u];i;i = edge[i].nex)
{
if(sz[edge[i].to])continue;
Fa[edge[i].to] = u;
dep[edge[i].to] = dep[u] + ;
dfs(edge[i].to);
sz[u] += sz[edge[i].to];
if(sz[hson[u]] < sz[edge[i].to])hson[u] = edge[i].to;
}
}
void dfs(int u,int tp)
{
top[u] = tp;st[u] = ++tot;id[tot] = u;
if(hson[u])dfs(hson[u],tp);
for(int i = head[u];i;i = edge[i].nex)
if(!st[edge[i].to])dfs(edge[i].to,edge[i].to);
ed[u] = tot;
}
int lca(int x,int y)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])swap(x,y);
x = Fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
int Q1(int u,int v){return ask(u) + ask(v) - * ask(lca(u,v)) + ;}
int Q2(int u){return Query(st[u],ed[u],,n,);}
int main()
{
scanf("%d %d",&n,&m);int tp,x,y;
for(int i = ;i < n;i++)
{
scanf("%d %d",&x,&y);
AddEdge(x,y);AddEdge(y,x);
}
dfs();dfs(,);
for(int i = ;i <= n;i++)updata(st[i],ed[i],,n,,),fa[i] = Fa[i];
while(m--)
{
scanf("%d",&tp);
if(tp == )scanf("%d",&x),access(x);
if(tp == )scanf("%d %d",&x,&y),printf("%d\n",Q1(x,y));
if(tp == )scanf("%d",&x),printf("%d\n",Q2(x));
}
}
[Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)的更多相关文章
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 692 Solved: 408[Submit][Status ...
- BZOJ4817: [Sdoi2017]树点涂色(LCT)
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ4817[Sdoi2017]树点涂色——LCT+线段树
题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...
- 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树
[BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
- BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)
题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ4817 [Sdoi2017]树点涂色 【LCT + 线段树】
题目 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进行这 ...
- 【bzoj4817】[Sdoi2017]树点涂色 LCT+LCA+线段树
题目描述 给出一棵n个点,以1为根的有根树,每个点初始染有互不相同的颜色.定义一条路径的权值为路径上的颜色种类数.现有m次操作,每次操作为以下三种之一: 1 x: 把点x到根节点的路径上所有的点染上一 ...
随机推荐
- IOS状态栏
IOS状态栏是什么地方? 它是IOS设备屏幕顶部显示信号以及电池的区域.状态栏默认的高度是20像素,状态栏在软件开发中有何作用?联网应用中可在自动帮用户下载数据时使用,推荐在状态栏中予以显示.状态栏可 ...
- redis源码分析之事务Transaction(下)
接着上一篇,这篇文章分析一下redis事务操作中multi,exec,discard三个核心命令. 原文地址:http://www.jianshu.com/p/e22615586595 看本篇文章前需 ...
- 在Github上删除一个项目
最近在Github上浏览,不小心fork了一个项目.想删除,现在记录下来. 1.点击选择fork的项目,以gubai为例 2.进入后,点击Settings 3.进入页面后,点击Delete this ...
- flask_SQLAlchemy 中常用的过滤和执行器
常用的SQLAlchemy查询过滤器 过滤器 说明 filter() 把过滤器添加到原查询上,返回一个新查询 filter_by() 把等值过滤器添加到原查询上,返回一个新查询 limit 使用指定的 ...
- 众皓网络(T 面试)
1.你们项目中哪里用到了Redis? 2.Redis中存储的数据,你们什么时候进行更新? 3.你用过消息队列吗? 4.你写的这个微服务项目拆分成了几个服务? 5.SpringCloud项目怎么部署的?
- 1-2 编程基础 GDB程序调试
简介 GDB是GNU发布的一款功能强大的程序调试工具.GDB主要完成下面三个方面的功能: 1.启动被调试程序 2.让被调试的程序在指定的位置停住. 3.当程序被停住时,可以检查程序状态(如变量值). ...
- IDEA无法编译源码,IDEA查看源码出现/* compiled code */
打开Settings -> Plugins 搜索dec,选中,确定,重启,解决
- excel组装sql
="INSERT INTO TABLE_XXXX (COLUMN_1, COLUMN_2, COLUMN_3, COLUMN_4, COLUMN_5, COLUMN_6, COLUMN_7, ...
- ubuntu18.04 server配置静态ip
最新发布的ubuntu18.04 server,启用了新的网络工具netplan,对于命令行配置网络参数跟之前的版本有比较大的差别,现在介绍如下:1.其网络配置文件是放在/etc/netplan/50 ...
- Linux中vim编辑器常用命令
移动光标 Ctrl+f:屏幕向下移动一页,相当于[Page Down]按键Ctrl+b:屏幕向上移动一页,相当与[PageUp]按键 0或功能键[Home]:数字‘0’:移动到这一行的最前面的字符处$ ...