题目描述

在X星球上有N个国家,每个国家占据着X星球的一座城市。由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的。 
X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失,而B国的国土也将归A国管辖。A国国王为了加强统治,会在A国和B国之间修建一条公路,即选择原A国的某个城市和B国某个城市,修建一条连接这两座城市的公路。 
同样为了便于统治自己的国家,国家的首都会选在某个使得其他城市到它距离之和最小的城市,这里的距离是指需要经过公路的条数,如果有多个这样的城市,编号最小的将成为首都。 
现在告诉你发生在X星球的战事,需要你处理一些关于国家首都的信息,具体地,有如下3种信息需要处理: 
1、A x y:表示某两个国家发生战乱,战胜国选择了x城市和y城市,在它们之间修建公路(保证其中城市一个在战胜国另一个在战败国)。 
2、Q x:询问当前编号为x的城市所在国家的首都。 
3、Xor:询问当前所有国家首都编号的异或和。

输入

第一行是整数N,M,表示城市数和需要处理的信息数。 
接下来每行是一个信息,格式如题目描述(A、Q、Xor中的某一种)。

输出

输出包含若干行,为处理Q和Xor信息的结果。

样例输入

10 10 
Xor 
Q 1 
A 10 1 
A 1 4 
Q 4 
Q 10 
A 7 6 
Xor 
Q 7 
Xor

样例输出

11 





2

题解

LCT维护子树信息

看了好几个小时的题解还是半懂不懂orz

先考虑连接两棵树

有两个性质

1.重心必在点数多的子树内

2.点数多的子树上重心移动的距离不超过点数少的子树的点数

然后就是连上之后,把这条路径拉出来,dfs一遍,枚举选哪一个点,然后判一下最优就好了

 // luogu-judger-enable-o2
//minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
using std::swap;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char obuf[<<],*o=obuf;
inline void print(int x){
if(x>) print(x/);
*o++=x%+;
}
const int N=;
int fa[N],st[N],sum[N],si[N],rev[N],ch[N][],top,s;
inline bool isroot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
inline void pushup(int x){sum[x]=sum[ch[x][]]+sum[ch[x][]]+si[x]+;}
inline void pushdown(int x){
if(rev[x]){
swap(ch[x][],ch[x][]);
rev[ch[x][]]^=,rev[ch[x][]]^=;
rev[x]=;
}
}
void rotate(int x){
int y=fa[x],z=fa[y],d=ch[y][]==x;
if(!isroot(y)) ch[z][ch[z][]==y]=x;
fa[x]=z,fa[y]=x,fa[ch[x][d^]]=y,ch[y][d]=ch[x][d^],ch[x][d^]=y,pushup(y);
}
void down(int x){
if(!isroot(x)) down(fa[x]);
pushdown(x);
}
void splay(int x){
down(x);
for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){
if(!isroot(y))
((ch[y][]==x)^(ch[z][]==y))?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
void access(int x){
for(int y=;x;x=fa[y=x])
splay(x),si[x]+=sum[ch[x][]],si[x]-=sum[ch[x][]=y],pushup(x);
}
void makeroot(int x){
access(x),splay(x),rev[x]^=;
}
int findroot(int x){
access(x),splay(x),pushdown(x);
while(ch[x][]) pushdown(x=ch[x][]);
return x;
}
void split(int x,int y){
makeroot(x),access(y),splay(y);
}
void link(int x,int y){
split(x,y),fa[x]=y,si[y]+=sum[x],pushup(y);
}
void dfs(int x){
pushdown(x);
if(ch[x][]) dfs(ch[x][]);
if(top>s) return;
st[++top]=x;
if(top>s) return;
if(ch[x][]) dfs(ch[x][]);
}
int main(){
//freopen("testdata.in","r",stdin);
int n=read(),m=read(),res=;
for(int i=;i<=n;++i) sum[i]=,res^=i;
while(m--){
char c;
while((c=getc())!='Q'&&c!='A'&&c!='X');
switch(c){
case 'A':{
int x=read(),y=read();
int tx=findroot(x),ty=findroot(y),ts;
res^=tx^ty;
splay(tx),splay(ty);
if(sum[tx]>sum[ty]||(sum[tx]==sum[ty]&&x<y)) swap(x,y),swap(tx,ty);
s=sum[tx],ts=sum[tx]+sum[ty],link(x,y),access(x),splay(ty);
top=,dfs(ty);int r=ty;
for(int i=;i<=top;++i){
splay(st[i]);int t=si[st[i]]++sum[ch[st[i]][]];
if(ts-t<t||(ts-t==t&&st[i]<=r)) r=st[i];
else break;
/*枚举原重心到连接点之间的路径
t表示枚举到某一点时另一棵子树的大小
如果这棵子树大于另一边或那啥,更新答案
否则之前的答案最优,直接退出*/
}
makeroot(r),res^=r;
break;
}
case 'Q':{
int x=read();
print(findroot(x)),*o++='\n';
break;
}
case 'X':{
print(res),*o++='\n';
break;
}
}
}
fwrite(obuf,o-obuf,,stdout);
return ;
}

BZOJ3510 首都的更多相关文章

  1. BZOJ3510 首都(LCT)

    即动态维护树的重心.考虑合并后的新重心一定在两棵树的重心的连线上.于是对每个点维护其子树大小,合并时在这条链的splay上二分即可.至于如何维护子树大小,见https://blog.csdn.net/ ...

  2. BZOJ3510首都(LCT)

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

  3. bzoj3510 首都 LCT 维护子树信息+树的重心

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3510 题解 首先每一个连通块的首都根据定义,显然就是直径. 然后考虑直径的几个性质: 定义:删 ...

  4. Bzoj3510首都

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  5. Some Conclusions.

    目录 DP 四边形不等式 数论 & 数学 数据结构 树链剖分 左偏树的性质及\(O(n)\)的构造 图论 树 二分图 竞赛图 平面图 双连通分量 字符串 后缀自动机 复杂度分析 没什么好写的. ...

  6. LCT维护子树信息

    有些题目,在要求支持link-cut之外,还会在线询问某个子树的信息.LCT可以通过维护虚边信息完成这个操作. 对于LCT上每个节点,维护两个两sz和si,后者维护该点所有虚儿子的信息,前者维护该点的 ...

  7. 【BZOJ3510】首都 LCT维护子树信息+启发式合并

    [BZOJ3510]首都 Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打 ...

  8. 洛谷P4299 首都(BZOJ3510)(LCT,树的重心,二分查找)

    Update:原来的洛谷U21715已成坑qwq 已经被某位管理员巨佬放进公共题库啦!又可以多一个AC记录啦! 洛谷题目传送门 其实也可以到这里交啦 思路分析 动态维护树的重心 题目中说到国家的首都会 ...

  9. 【bzoj3510】首都 LCT维护子树信息(+启发式合并)

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

随机推荐

  1. 安装atop笔记

    atop 官网: https://www.atoptool.nl/downloadatop.php 1.直接下载源码安装: https://www.atoptool.nl/download/atop- ...

  2. book pile SGU - 271

    有n本书从上到下摞在一起,有两种操作.ADD(C)表示把一本新书C放到这一摞书的最顶上,ROTATE表示将前K本书进行反转.在一系列操作后输出最后书的顺序 分析: 当时听别人讲这个题的时候很懵逼,后来 ...

  3. nginx源码完全注释(1)ngx_alloc.h / ngx_alloc.c

    首先看 ngx_alloc.h 文件,主要声明或宏定义了 ngx_alloc,ngx_calloc,ngx_memalign,ngx_free. /* * Copyright (C) Igor Sys ...

  4. ios加载本地html

    UIWebView加载工程本地网页与本地图片 - (void)viewDidLoad { [super viewDidLoad]; NSString *filePath = [[NSBundle ma ...

  5. LVS集群中实现的三种IP负载均衡技术

    LVS有三种IP负载均衡技术:VS/NAT,VS/DR,VS/TUN. VS/NAT的体系结构如图所示.在一组服务器前有一个调度器,它们是通过Switch/HUB相连接的.这些服务器 提供相同的网络服 ...

  6. 快速搭建Wordpress

    1. 下载:ZentaoPMS作为Mysql Apach Php的基础环境: 2. 下载:Wordpress安装包: 3. 将Wordpress解压,放置于ZentaoPMS的Xampp的htdocs ...

  7. tornado异步请求非阻塞-乾颐堂

    前言 也许有同学很迷惑:tornado不是标榜异步非阻塞解决10K问题的嘛?但是我却发现不是torando不好,而是你用错了.比如最近发现一个事情:某网站打开页面很慢,服务器cpu/内存都正常.网络状 ...

  8. UDP问题

    这两天使用C#的UdpClient,本机的服务是采用MFC的socket发的,用C#做客户端,然后客户端启动时,出现该条错误信息 ==通常每个套接字地址(协议/网络地址/端口)只允许使用一次. 笔记的 ...

  9. jQuary总结1:jQuary的优点和地位

    1 什么是jQuery? jQuery是一个快速,小巧,功能丰富的JavaScript库. javascript库: 就是存放javascript代码的仓库 jQuery作为一个迭代多年的优秀框架,是 ...

  10. javascript总结48:正则表达式(RegExp)

    1 正则表达式(英语:Regular Expression) 正则表达式(英语:Regular Expression,在代码中常简写为regex.regexp或RE)使用单个字符串来描述.匹配一系列符 ...