Luogu P4299 首都 LCT
既然是中文题目,这里便不给题意。
分析:
这个题的做法据说是启发式合并?
但是我不会啊……
进入正题,LCT是怎样做掉这道题的。记得在前面的一篇《大融合》的题解中,介绍过LCT维护子树信息的做法。
一句话概括就是要维护虚子树和实子树的size,适时修改,保持其正确性。
这道题关键并不在这,但我们必须要维护这样一个信息才可以做。
很简单很直观的一个想法,因为我们每次合并两棵树时,新的重心必然出现在原来两个重心的路径上。
这是为什么?我们假设如果不在这条路径上,而是其中一棵树的其他子树的某一点,那么我们发现这一点比起之前,size较大的一棵子树上又缀了一棵树(以这个点为根),所以一定不优。
于是我们就合并树后把两棵原树的重心打通,(放到一个splay里),这时候尺寸就派上用场了,我们就在这个splay里查找,因为重心反正肯定存在于这个splay中了,那么我们就维护一个左尺寸,一个右尺寸。左边大了我们就让重心往左移动,右边大了就往右移动,直到两边的尺寸都小于等于总尺寸的一半,就好啦!(别忘了多个重心时的编号最小化)
代码:
- #include<bits/stdc++.h>
- #define lc(x) t[x][0]
- #define rc(x) t[x][1]
- using namespace std;
- const int N=;
- const int inf=0x3f3f3f3f;
- struct LCT{
- int t[N][],s[N],rev[N],fa[N],sx[N],sz[N],tp;
- void pushup(int x){
- sz[x]=sz[lc(x)]+sz[rc(x)]+sx[x]+;
- } bool pdrt(int x){
- return rc(fa[x])!=x&&lc(fa[x])!=x;
- } void revers(int x){
- rev[x]^=;swap(lc(x),rc(x));
- } void pushdown(int x){
- if(rev[x]){ rev[x]=;
- if(lc(x)) revers(lc(x));
- if(rc(x)) revers(rc(x));
- } return ;
- } void rotate(int x){
- int y=fa[x];int z=fa[y];
- int dy=(rc(y)==x),dz=(rc(z)==y);
- if(!pdrt(y)) t[z][dz]=x;
- t[y][dy]=t[x][dy^];fa[t[y][dy]]=y;
- t[x][dy^]=y;fa[y]=x;fa[x]=z;
- pushup(y);return ;
- } void splay(int x){
- s[++tp]=x;
- for(int i=x;!pdrt(i);i=fa[i])
- s[++tp]=fa[i];
- while(tp) pushdown(s[tp--]);
- while(!pdrt(x)){
- int y=fa[x];int z=fa[y];
- if(!pdrt(y))
- if(rc(y)==x^rc(z)==y) rotate(x);
- else rotate(y);rotate(x);
- } pushup(x);return ;
- } void access(int x){
- for(int i=;x;x=fa[i=x])
- splay(x),sx[x]+=sz[rc(x)],
- sx[x]-=sz[rc(x)=i],pushup(x);
- } void mkrt(int x){
- access(x);splay(x);revers(x);
- } void split(int x,int y){
- mkrt(x);access(y);splay(y);
- } void link(int x,int y){
- split(x,y);sx[fa[x]=y]+=sz[x];
- pushup(y);
- } int update(int x){
- int l,r,o=sz[x]&,sm=sz[x]>>,
- ls=,rs=,np=inf,nl,nr;
- while(x){
- pushdown(x);
- nl=sz[l=lc(x)]+ls;nr=sz[r=rc(x)]+rs;
- if(nl<=sm&&nr<=sm){
- if(o){np=x;break;}
- else if(np>x) np=x;
- } if(nl<nr) ls+=sz[l]+sx[x]+,x=r;
- else rs+=sz[r]+sx[x]+,x=l;
- } splay(np);return np;
- }
- }t;int n,m,fa[N];
- int get(int x){
- return fa[x]==x?x:fa[x]=get(fa[x]);
- } int main(){
- char c[];int rox=;//尤为重要,必须赋0;
- scanf("%d%d",&n,&m);
- for(int i=;i<=n;i++)
- t.sz[i]=,fa[i]=i,rox^=i;
- while(m--){
- scanf("%s",c);int x,y,z;
- if(c[]=='A'){
- scanf("%d%d",&x,&y);t.link(x,y);
- t.split(x=get(x),y=get(y));
- z=t.update(y);rox=(rox^x^y^z);
- fa[x]=fa[y]=fa[z]=z;
- } else if(c[]=='Q'){
- scanf("%d",&x);
- printf("%d\n",get(x));
- } else printf("%d\n",rox);
- } return ;
- }
Luogu P4299 首都 LCT的更多相关文章
- luogu P4299 首都
题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...
- P4299 首都
题目 P4299 首都 做法 这题是动态维护树的重心,连边后找到两棵树的重心拉一条链(性质:新重心在链上),然后暴力爬 要注意: 1.是找重心的过程中要先把旋转标记放下来,因为\(Splay(x)\) ...
- 洛谷P4299 首都(BZOJ3510)(LCT,树的重心,二分查找)
Update:原来的洛谷U21715已成坑qwq 已经被某位管理员巨佬放进公共题库啦!又可以多一个AC记录啦! 洛谷题目传送门 其实也可以到这里交啦 思路分析 动态维护树的重心 题目中说到国家的首都会 ...
- 【bzoj3510】首都 LCT维护子树信息(+启发式合并)
题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...
- 【BZOJ3510】首都 LCT维护子树信息+启发式合并
[BZOJ3510]首都 Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打 ...
- BZOJ 3510 首都 (LCT)
洛谷P4299传送门 题目大意:给你一颗树,边是一条一条连上去的 在连接过程中会存在询问,询问当前节点所在联通块(其实是一颗树)的重心是哪个节点 以及森林中所有树的重心的异或和 在做这道题之前,要先了 ...
- bzoj3510 首都 LCT 维护子树信息+树的重心
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3510 题解 首先每一个连通块的首都根据定义,显然就是直径. 然后考虑直径的几个性质: 定义:删 ...
- BZOJ.3510.首都(LCT 启发式合并 树的重心)
题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...
- BZOJ 3510: 首都 LCT + multiset维护子树信息 + 树的重心
Code: #include<bits/stdc++.h> #define maxn 200000 #define inf 1000000000 using namespace std; ...
随机推荐
- [App Store Connect帮助]八、维护您的 App(3)将 App 恢复至 App Store
如果您已将 App 从 App Store 中移除,之后创建了该 App 的一个新版本,那么即使新版本被“App 审核”批准,App 状态也仍会是“被开发者下架”.若要发布新版本,您必须首先将其恢复至 ...
- influxdb数据库增加身份认证(windows)三
接上一节,增加数据库身份认证 1.修改Config配置文件auth-enabled为true 2.然后重新载入最新的config配置文件打开数据库 3.验证身份认证功能是否已打开 说明身份认证功能已打 ...
- RT-Thread 设备驱动ADC浅析与改进
OS版本:RT-Thread 4.0.0 芯片:STM32F407 下面时官方ADC提供的参考访问接口 访问 ADC 设备 应用程序通过 RT-Thread 提供的 ADC 设备管理接口来访问 ADC ...
- HttpSession讲解
1:session进行身份验证的原理: 当客户端第一次访问服务器的时候,此时客户端的请求中不携带任何标识给服务器,所以此时服务器无法找到与之对应的 session,所以会新建session对象,当服务 ...
- POJ 2255 Tree Recoveryw(二叉树)
题目原网址:http://poj.org/problem?id=2255 题目中文翻译: Description 小瓦伦丁非常喜欢玩二叉树. 她最喜欢的游戏是用大写字母构造的随机二叉树. 这是她的一个 ...
- ACM二分查找模板
int main(){ == key int m; while ( l <= r ) { m = ( l + r ) >> 1; if ( x[m] == key ) return ...
- ZooKeeper通过ACL修复未授权访问漏洞
默认情况下ZooKeeper允许匿名访问,因此在安全漏洞扫描中暴漏未授权访问漏洞. 一.参考资料 <ZooKeeper 笔记(5) ACL(Access Control List)访问控制列表& ...
- 关于minSdkVersion="8" 升级appcompat_v7包主题"Theme.AppCompat.Light"等不存在的问题
关于minSdkVersion="8" 升级后,又不想用 appcompat_v7包, 那么appcompat_v7主题"Theme.AppCompat.Light&qu ...
- 2016/10/29 Action类中execute方法的使用
第一步:先配置web.xml文件 <filter> <filter-name>struts2</filter-name> <filter-class>o ...
- 利用正则将xml数据解析为数组
function xml_to_array( $xml ) { $reg = '/<(\w+)[^>]*>([\x00-\xFF]*)<\/\1>/'; if(preg_ ...