BZOJ 3510 首都 (LCT)
题目大意:给你一颗树,边是一条一条连上去的
在连接过程中会存在询问,询问当前节点所在联通块(其实是一颗树)的重心是哪个节点
以及森林中所有树的重心的异或和
在做这道题之前,要先了解树的重心的一个性质:
两棵树合并时,新树的重心在合并后,原来两颗树的重心的两个节点构成的那条链上
了解了这条性质,思路就不难想了
当连接两个节点时,先寻找它们所在原树的重心,然后连接这两个节点,在取出两个原树重心那两个节点构成的那条链
每次寻找重心,连接节点,取出重心形成了链,复杂度约为
如果我们暴力跑这条链,最差的情况是每次合并时,两颗树都是等长的链,然后像线段树那样从下往上合并,合并次数最多是次,注意符合条件的重心最多只有2个,且子树的大小符合单调性,当越过所有重心时,及时跳出循环防止卡常
总复杂度
然而我还是喜闻乐见得被卡常了
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define N 200100
using namespace std; int n,m,tp,num,xsum;
int stk[N],que[N]; struct LinkCutTree{
#define ls ch[x][0]
#define rs ch[x][1]
int fa[N],ch[N][],sz[N],sum[N],rv[N];
il int idf(int x){return ch[fa[x]][]==x?:;}
il void rev(int x){swap(ls,rs),rv[x]^=;}
il int isroot(int x){return (ch[fa[x]][]!=x&&ch[fa[x]][]!=x)?:;}
il void pushup(int x){sum[x]=sum[ls]+sum[rs]+sz[x]+;}
il void pushdown(int x)
{
if(rv[x]){
if(ls) rev(ls);
if(rs) rev(rs);
rv[x]^=;
}
}
il void rot(int x)
{
int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
if(!isroot(y)) ch[ff][py]=x;fa[x]=ff;
ch[y][px]=ch[x][px^],fa[ch[x][px^]]=y;
ch[x][px^]=y,fa[y]=x;
pushup(y),pushup(x);
}
void splay(int x)
{
int y=x;stk[++tp]=x;
while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];}
while(tp){pushdown(stk[tp--]);}
while(!isroot(x))
{
y=fa[x];
if(isroot(y)) rot(x);
else if(idf(y)==idf(x)) rot(y),rot(x);
else rot(x),rot(x);
}
}
void access(int x){
for(int y=;x;y=x,x=fa[x])
splay(x),sz[x]-=sum[y],sz[x]+=sum[ch[x][]],ch[x][]=y,pushup(x);}
il void mkroot(int x){access(x),splay(x),rev(x);}
il void split(int x,int y){mkroot(y),access(x),splay(x);}
il int findrt(int x){
access(x),splay(x);
while(){
pushdown(x);
if(!ch[x][])break;
x=ch[x][];}
splay(x);return x;
}
void mid_dfs(int x)
{
pushdown(x);
if(ls) mid_dfs(ls);
que[++num]=x;
if(rs) mid_dfs(rs);
}
il void link(int x,int y)
{
int gx=findrt(x),gy=findrt(y);
xsum=xsum^gx^gy;
if(sum[gx]<sum[gy]) swap(x,y),swap(gx,gy);
split(x,y),fa[y]=x,sz[x]+=sum[y],pushup(x);
num=,split(gy,gx),mid_dfs(gy);
int ma=sum[gy]/,ans=0x3f3f3f3f;
for(int i=;i<=num;i++){
splay(que[i]);
if(sum[ch[que[i]][]]<=ma&&sum[ch[que[i]][]]<=ma&&que[i]<ans)
ans=que[i];
if(sum[ch[que[i]][]]>ma) break;}
mkroot(ans);
xsum^=ans;
}
#undef ls
#undef rs
}lct;
int gint()
{
int rett=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){rett=(rett<<)+(rett<<)+c-'';c=getchar();}
return rett*fh;
}
void gchar(char str[])
{
int p=;char c=getchar();
while(!((c>='A'&&c<='Z')||(c>='a'&&c<='z'))){c=getchar();}
while((c>='A'&&c<='Z')||(c>='a'&&c<='z')){str[p++]=c;c=getchar();}
str[p]='\0';
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) xsum^=i;
char q[];int x,y;
for(int i=;i<=m;i++)
{
gchar(q);
if(q[]=='A'){
x=gint(),y=gint();
lct.link(x,y);
}else if(q[]=='Q'){
x=gint();
printf("%d\n",lct.findrt(x));
}else printf("%d\n",xsum);
}
return ;
}
BZOJ 3510 首都 (LCT)的更多相关文章
- BZOJ.3510.首都(LCT 启发式合并 树的重心)
题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...
- BZOJ 3510: 首都 LCT + multiset维护子树信息 + 树的重心
Code: #include<bits/stdc++.h> #define maxn 200000 #define inf 1000000000 using namespace std; ...
- BZOJ 3510 - 首都 「 $LCT$ 动态维护树的重心」
这题 FlashHu 的优化思路值得借鉴 前置引理 树中所有点到某个点的距离和中,到重心的距离和是最小的. 把两棵树通过某一点相连得到一颗新的树,新的树的重心必然在连接原来两棵树重心的路径上. 一棵树 ...
- 【刷题】BZOJ 3510 首都
Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从 ...
- bzoj3510 首都 LCT 维护子树信息+树的重心
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3510 题解 首先每一个连通块的首都根据定义,显然就是直径. 然后考虑直径的几个性质: 定义:删 ...
- 【bzoj3510】首都 LCT维护子树信息(+启发式合并)
题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...
- 【BZOJ3510】首都 LCT维护子树信息+启发式合并
[BZOJ3510]首都 Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打 ...
- BZOJ 2959 长跑 (LCT+并查集)
题面:BZOJ传送门 当成有向边做的发现过不去样例,改成无向边就忘了原来的思路.. 因为成环的点一定都能取到,我们把它们压成一个新点,权值为环上所有点的权值和 这样保证了图是一颗森林 每次询问转化为, ...
- BZOJ 3306: 树 LCT + set 维护子树信息
可以作为 LCT 维护子树信息的模板,写的还是比较优美的. 本地可过,bzoj 时限太紧,一直 TLE #include<bits/stdc++.h> #define setIO(s) f ...
随机推荐
- IOS - 绘制文字 drawInRect: withFont: not working
在图形绘制中,我们经常会需要绘制文本,但我在给PDF上绘制Text时,始终绘制不上, 使用过: [str drawInRect:cubeRect withAttributes:attrs]; CGCo ...
- 用Js写贪吃蛇
使用Javascript做贪吃蛇小游戏, 1.自定义地图宽高,蛇的初始速度 2.食物随机出现 3.蛇的样式属性 4.贪吃蛇玩法(吃食物,碰到边界,吃食物后加速,计分,) <!DOCTYPE ht ...
- Ubuntu安装Docker 适合Ubuntu17.04版本
Docker介绍 Docker是一个开源的容器引擎,它有助于更快地交付产品.Docker可将应用程序和基础设施层隔离,并且将基础设施当作程序一样进行管理.使用Docker,可以更快地打包,测试以及部署 ...
- Centos文件查看命令字符
文件(夹)查看类命令 ls--显示指定目录下内容 说明:ls 显示结果以不同的颜色来区分文件类别.蓝色代表目录,灰色代表普通文件,绿色代表可执行文件,红色代表压缩文件,浅蓝色代表链接文件. -a--- ...
- Java启动问题-Application Server was not connected before run configuration stop, reason: Unable to ping server at localhost:1099
环境一直跑的挺好的,突然报这么一个错误,百思不得其解. 网上查询之后才想起来,自己当时为了IE能运行浪潮服务器的远程console,将环境变量里面的java换成了32位版本的. 修改jre版本与环境变 ...
- hibernate框架总结
实体类编写规则1 实体类里面属性私有的 2 私有属性使用公开的set和get方法操作 3 要求实体类有属性作为唯一值(一般使用id值) 4 实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装 ...
- 【转】一分钟读懂互联网广告竞价策略GFP+GSP+VCG
参考这篇文章: http://ju.outofmemory.cn/entry/116780 一分钟读懂互联网广告竞价策略GFP+GSP+VCG 两个广告位,三家广告主竞价,广告平台究竟应该制定广告竞价 ...
- POJ 1236 Network of Schools 强连通图
Description A number of schools are connected to a computer network. Agreements have been developed ...
- jQuery Video Extend
HTML5视频扩展插件 能够加入Logo 加入标记 用法: 下载:jquery-video-extend <script src="js/jquery-2.1.4.min.js&quo ...
- 原来C++之父在大摩工作呀,并且还是总经理。。
摩根士丹利信息技术部门简历接收即将截止.请同学们抓紧投递 摩根士丹利9月.10月将在中国各大高校举办包含技术讲座.信息分享会以及校园宣讲会在 内的一系列校园活动.同学们将有机会和摩根士丹利高管以及返校 ...