解析

动态维护树的重心
关键性质:两棵树合并时,新的重心一定在两个原重心之间的路径上
把两个重心之间的路径提出来,利用splay本身的二叉结构二分即可
注意虚子树信息的处理
不要忘记pushdown

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=3e5+100;
const int mod=1e9+7;
const double eps=1e-9;
inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int n,m;
int flag;
int tr[N][2],f[N],rev[N];
int siz[N],siz0[N];
#define ls(u) tr[u][0]
#define rs(u) tr[u][1]
inline bool isroot(int x){return ls(f[x])!=x&&rs(f[x])!=x;
}
inline bool which(int x){return rs(f[x])==x;
}
inline void pushup(int x){if(x) siz[x]=siz[ls(x)]+siz[rs(x)]+siz0[x]+1;return;
}
inline void Rev(int x){if(x){rev[x]^=1;swap(tr[x][0],tr[x][1]);}return;
}
inline void pushdown(int x){if(rev[x]){rev[x]=0;Rev(tr[x][0]);Rev(tr[x][1]);}return;
}
void print(int x){if(!x) return;pushdown(x);printf("x=%d ls=%d rs=%d fa=%d siz=%d siz0=%d\n",x,ls(x),rs(x),f[x],siz[x],siz0[x]);print(ls(x));print(rs(x));
}
void Debug(){//printf("debug:\n");for(int i=1;i<=n;i++) if(isroot(i)) print(i);putchar('\n');
}
inline void rotate(int x){int fa=f[x],gfa=f[fa];int d=which(x),son=tr[x][d^1];f[x]=gfa;if(!isroot(fa)) tr[gfa][which(fa)]=x;f[fa]=x;tr[x][d^1]=fa;if(son){f[son]=fa;}tr[fa][d]=son;pushup(fa);pushup(x);return;
}
int zhan[N];
inline void splay(int x){int y=x,top(0);zhan[++top]=y;while(!isroot(y)) zhan[++top]=y=f[y];while(top){//printf("  pushdown:%d\n",y);pushdown(zhan[top--]);}for(int fa;fa=f[x],!isroot(x);rotate(x)){if(!isroot(fa)) which(x)==which(fa)?rotate(fa):rotate(x);}return;
}
inline void access(int x){for(int y=0;x;y=x,x=f[x]){splay(x);siz0[x]+=siz[rs(x)];siz0[x]-=siz[y];rs(x)=y;pushup(x);if(y) f[y]=x;}return;
}
inline void makeroot(int x){//if(flag) printf("makeroot:%d\n\n",x);access(x);//if(flag) printf("access:\n"),Debug();splay(x);Rev(x);return;
}
inline void link(int x,int y){makeroot(x);access(y);splay(y);siz0[y]+=siz[x];f[x]=y;pushup(y);return;
}
inline void split(int x,int y){//if(flag) printf("split:(%d %d)\n",x,y);makeroot(x);//printf("makeroot:\n");Debug();access(y);//printf("access:\n");Debug();splay(y);//printf("splay:\n");Debug();return;
}int fa[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);
}int solve(int x,int y){//printf("pre:\n");Debug();split(y,x);//Debug();int l(0),r(0),lsum(0),rsum(0),ans(0),tot=siz[x];while(x){pushdown(x);l=ls(x);r=rs(x);int lsiz=lsum+siz[l],rsiz=rsum+siz[r];//printf("x=%d l=%d r=%d tot=%d lsiz=%d rsiz=%d\n",x,l,r,tot,lsiz,rsiz);if(lsiz<=tot/2&&rsiz<=tot/2){           if(!ans||x<ans) ans=x;if(tot&1) break;}if(lsiz>rsiz){rsum+=siz[r]+siz0[x]+1;x=l;}else{lsum+=siz[l]+siz0[x]+1;x=r;}//printf("  lsum=%d rsum=%d\n",lsum,rsum);}splay(ans);return ans;
}int now;
char s[10];
int main() {#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifn=read();m=read();for(int i=1;i<=n;i++){siz[i]=1;now^=i;fa[i]=i;}for(int i=1;i<=m;i++){scanf(" %s",s+1);//if(i==5) flag=1;if(s[1]=='X') printf("%d\n",now);else if(s[1]=='Q') printf("%d\n",find((int)read()));else{int x=read(),y=read();link(x,y);if(flag) printf("link:\n"),Debug();x=find(x);y=find(y);int z=solve(x,y);now^=x^y;now^=z;fa[z]=fa[x]=fa[y]=z;//printf("i=%d x=%d y=%d z=%d\n\n",i,x,y,z);}//if(flag) printf("finish:\n"),Debug();}return 0;
}

P4299 首都(LCT、重心)相关推荐

  1. Luogu P4299 首都 LCT

    既然是中文题目,这里便不给题意. 分析: 这个题的做法据说是启发式合并? 但是我不会啊-- 进入正题,LCT是怎样做掉这道题的.记得在前面的一篇<大融合>的题解中,介绍过LCT维护子树信息 ...

  2. luogu P4299 首都

    题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...

  3. [luogu-P4299] 首都(并查集 + LCT动态维护树的重心 / 维护虚儿子信息)

    problem luogu-P4299 solution 本题考察了很经典的模型,运用了很经典的解法. 本题用到了重心的两个性质: 两棵树合并为同一棵树时,新的重心一定在原来两棵树各自重心的路径上. ...

  4. BZOJ3510 首都

    题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的.  X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失 ...

  5. bzoj 3510 首都

    Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的.  X星球上战乱频发,如果A国打败了B国,那么B国将永远 ...

  6. 树形dp ——树的重心

    1.只需要求出最大子树中节点数最小的数目即可 题意:有一个国王要把他的领土分给两个儿子,国王的领土是一棵树,N个结点,N-1条边把这些结点连起来,现在大小儿子要选择一个点作为他的首都,那么除首都分别是 ...

  7. 【BZOJ-2888】资源运输 LCT + 启发式合并

    2888: 资源运输 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 63  Solved: 33 [Submit][Status][Discuss] ...

  8. 「LOJ2474」「2018 集训队互测」北校门外的未来-笛卡尔树及其扩展+LCT

    Description 链接 Solution 对于一棵树 TTT,定义其的笛卡尔树 C(T)C(T)C(T) 满足: 堆性质,即祖先的权值(本题中为标号)一定大于子孙的权值. 搜索树性质,即任意子树 ...

  9. [渝粤教育] 首都师范大学 走进舞蹈艺术 参考 资料

    教育 -走进舞蹈艺术-章节资料考试资料-首都师范大学[] 自然状态的萌动 1.[判断题]人类的舞蹈能力是与生俱来的吗? A.正确 B.错误 参考资料[ ] 情感语言的开启 1.[填空题]人类最初通过 ...

最新文章

  1. 分分钟带你杀入Kaggle Top 1%
  2. ASP.NET页面借助IFrame提交表单数据所遇到的问题
  3. oracle中or的替函数,Oracle常用内置Or自定义函数-SQL宝典
  4. python文件的编译
  5. 从Inception v1,v2,v3,v4,RexNeXt到Xception再到MobileNets,ShuffleNet,MobileNetV2
  6. 查看动态代理生成的代理类字节码
  7. 【动态规划】书的复制 (ssl 1203)
  8. SQL Server系统存储过程
  9. 网络调试助手(NetAssist)java socket通讯代码
  10. m3u8手机批量转码_M3U8批量转换app-M3U8批量转换MP4软件下载v1.0 安卓版-西西软件下载...
  11. Codeforces - DZY Loves Sequences
  12. 【阿里巴巴-飞猪旅行-内推】2020年应届实习生招聘
  13. 运维祈求不宕机_一份运维监控的终极秘籍!监控不到位,宕机两行泪
  14. Java显示棋盘_Java的GUI学习:显示国际棋盘
  15. dellemc服务器中文语言设置,美版windows10系统设置中文语言的方法
  16. Tuscany插件的安装
  17. 成都敏之澳:拼多多关键词选词关键要素是什么?
  18. linux 操作系统root账号被锁定的两种解决方法
  19. Traefik v2.9-IngressRoute
  20. 读书笔记-Icepak自然冷却模拟设置步骤

热门文章

  1. java jar包 平滑重启,nginx 平滑重启的实现方法
  2. 华为二面!!!被问常用API,这也太偏门了吧,我秀了一波hhhh~
  3. Docker最全教程之使用Docker搭建Java开发环境
  4. java 方法执行结束局部变量释放_Java方法执行的内存模型
  5. java原生的编译软件_Java 转原生平台代码 RoboVM
  6. sqoop将hive导出到mysql_Sqoop hive导出到mysql[转]
  7. fpga开发教程 labview_LabVIEW项目样例 - NI VST FPGA软件编程使用步骤与实例教程
  8. 数据结构——交换左右子树
  9. 软件构造学习笔记-实验1
  10. [JavaWeb-HTTP]HTTP_请求消息_请求头请求体