BZOJ3510首都(LCT)
Description
在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:询问当前所有国家首都编号的异或和。
Input
第一行是整数N,M,表示城市数和需要处理的信息数。
接下来每行是一个信息,格式如题目描述(A、Q、Xor中的某一种)。
Output
输出包含若干行,为处理Q和Xor信息的结果。
Sample Input
Xor
Q 1
A 10 1
A 1 4
Q 4
Q 10
A 7 6
Xor
Q 7
Xor
Sample Output
11
1
1
1
2
6
2
解题思路:
主要是动态维护重心。
可以证明,新的中心在原来两个树中心路径上。
那么就把这段路径提取出来找就好了。
注意将重心旋转至根,保证时间复杂度。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll tr[spc].ch[0]
#define rrr tr[spc].ch[1]
#define ls ch[0]
#define rs ch[1]
struct trnt{
int ch[];
int fa;
int lzt;
int wgt;
int wgti;
int ff;
bool anc;
}tr[];
int st[];
int tp;
int n,m;
int Xorsum;
char cmd[];
bool whc(int spc)
{
return tr[tr[spc].fa].rs==spc;
}
int finf(int x)
{
return tr[x].ff==x?x:tr[x].ff=finf(tr[x].ff);
}
void pushup(int spc)
{
if(!spc)
return ;
tr[spc].wgt=tr[spc].wgti+tr[lll].wgt+tr[rrr].wgt+;
return ;
}
void trr(int spc)
{
if(!spc)
return;
std::swap(lll,rrr);
tr[spc].lzt^=;
return ;
}
void pushdown(int spc)
{
if(tr[spc].lzt)
{
trr(lll);
trr(rrr);
tr[spc].lzt=;
}
return ;
}
void recal(int spc)
{
if(!tr[spc].anc)
recal(tr[spc].fa);
pushdown(spc);
return ;
}
void rotate(int spc)
{
int f=tr[spc].fa;
bool k=whc(spc);
tr[f].ch[k]=tr[spc].ch[!k];
tr[spc].ch[!k]=f;
if(tr[f].anc)
{
tr[spc].anc=;
tr[f].anc=;
}else
tr[tr[f].fa].ch[whc(f)]=spc;
tr[spc].fa=tr[f].fa;
tr[f].fa=spc;
tr[tr[f].ch[k]].fa=f;
pushup(f);
pushup(spc);
return ;
}
void splay(int spc)
{
recal(spc);
while(!tr[spc].anc)
{
int f=tr[spc].fa;
if(tr[f].anc)
{
rotate(spc);
break;
}
if(whc(spc)^whc(f))
rotate(spc);
else
rotate(f);
rotate(spc);
}
return ;
}
void access(int spc)
{
int lst=;
while(spc)
{
splay(spc);
tr[spc].wgti+=tr[rrr].wgt;
tr[spc].wgti-=tr[lst].wgt;
tr[rrr].anc=;
tr[lst].anc=;
rrr=lst;
pushup(spc);
lst=spc;
spc=tr[spc].fa;
}
return ;
}
void Mtr(int spc)
{
access(spc);
splay(spc);
trr(spc);
return ;
}
void split(int x,int y)
{
Mtr(x);
access(y);
splay(y);
return ;
}
void link(int x,int y)
{
split(x,y);
tr[x].fa=y;
tr[y].wgti+=tr[x].wgt;
pushup(y);
return ;
}
int Gravity(int spc)
{
int lwgt=;
int rwgt=;
int tot=tr[spc].wgt/;
int odd=tr[spc].wgt&;
int ans=0x3f3f3f3f;
while(spc)
{
pushdown(spc);
int ll,rr;
ll=lwgt+tr[lll].wgt;
rr=rwgt+tr[rrr].wgt;
if(ll<=tot&&rr<=tot)
{
if(odd)
{
ans=spc;
break;
}
if(ans>spc)
ans=spc;
}
if(ll>rr)
{
rwgt+=(tr[spc].wgti+tr[rrr].wgt+);
spc=lll;
}else{
lwgt+=(tr[spc].wgti+tr[lll].wgt+);
spc=rrr;
}
}
splay(ans);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
tr[i].wgt=tr[i].anc=;
tr[i].ff=i;
Xorsum^=i;
}
while(m--)
{
scanf("%s",cmd);
if(cmd[]=='A')
{
int x,y;
scanf("%d%d",&x,&y);
link(x,y);
x=finf(x);
y=finf(y);
split(x,y);
int g=Gravity(y);
Xorsum=Xorsum^x^y^g;
tr[x].ff=tr[y].ff=tr[g].ff=g;
}
if(cmd[]=='Q')
{
int x;
scanf("%d",&x);
printf("%d\n",finf(x));
}
if(cmd[]=='X')
{
printf("%d\n",Xorsum);
}
}
return ;
}
BZOJ3510首都(LCT)的更多相关文章
- bzoj3510 首都 LCT 维护子树信息+树的重心
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3510 题解 首先每一个连通块的首都根据定义,显然就是直径. 然后考虑直径的几个性质: 定义:删 ...
- 【BZOJ3510】首都 LCT维护子树信息+启发式合并
[BZOJ3510]首都 Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打 ...
- 【bzoj3510】首都 LCT维护子树信息(+启发式合并)
题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...
- BZOJ3510 首都(LCT)
即动态维护树的重心.考虑合并后的新重心一定在两棵树的重心的连线上.于是对每个点维护其子树大小,合并时在这条链的splay上二分即可.至于如何维护子树大小,见https://blog.csdn.net/ ...
- BZOJ3510 首都
题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...
- Bzoj3510首都
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- BZOJ.3510.首都(LCT 启发式合并 树的重心)
题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...
- Luogu P4299 首都 LCT
既然是中文题目,这里便不给题意. 分析: 这个题的做法据说是启发式合并? 但是我不会啊…… 进入正题,LCT是怎样做掉这道题的.记得在前面的一篇<大融合>的题解中,介绍过LCT维护子树信息 ...
- BZOJ 3510: 首都 LCT + multiset维护子树信息 + 树的重心
Code: #include<bits/stdc++.h> #define maxn 200000 #define inf 1000000000 using namespace std; ...
随机推荐
- C语言:具体解释指针
指针应该算得上是c语言的精华,但也是难点. 非常多教程或者博客都有对其具体的解说与分析. 我这一节的内容,也是解说指针.但我会尽量使用图解的方式,使大家非常easy理解及掌握. 一.基本使用 先来看看 ...
- ProFTPD 的 mod_lang模块
ProFTPD 的 mod_lang模块http://www.proftpd.org/docs/modules/mod_lang.html安装该mod_lang模块随ProFTPD一起分发.要在pro ...
- vim基础学习之EX命令
:tabnew -创建新标签 :split(sp)-垂直分割窗口 如果没有打开新的文件,那么会打开原来窗口的文件 :vsplit(vsp)-水平分割窗口 如果没有打开新的文件,那么会打开原来窗口的文件 ...
- 在使用FireFox浏览器时,经常打开新标签,页面总是不断自动刷新,解决办法
可以用如下方法尝试(逐个尝试,看看哪个管用): 1.地址栏输入 about:support,右上角有个翻新Firefox,点击,等待浏览器重启,即可. 2.点击:工具-附加组件,把“火狐主页和标签管理 ...
- android 动画xml属性具体解释
/** * 作者:crazyandcoder * 联系: * QQ : 275137657 * email: lijiwork@sina.com * 转载请注明出处! */ android 动画属性具 ...
- /dev/shm和swap差别与联系
1.基本理论 /dev/shm这个文件是寄生虫,寄存在内存中 swap是暂时在硬盘中划分一个区域,把它作为内存使用 2.怎样查看 使用df -lh能够查看/dev/shm 使用free -m能够查看s ...
- qmake生成Visual Studio工程
整个Qt在Windows中都可以通过批处理来编译,当编译好Qt后,会生成qmake.exe. 在没有安装Qt-VS-Addin的情况下,如何使用别人提供的Qt *.pro项目文件呢? 使用qmake可 ...
- wifidog用php实现验证流程
原创性声明 此博文的出处 为 http://blog.csdn.net/zhujunxxxxx/article/details/25384909假设进行转载请注明出处.本文作者原创,邮箱zhujunx ...
- 如何使用jquery判断一个元素是否含有一个指定的类(class)
如何使用jquery判断一个元素是否含有一个指定的类(class) 一.总结 一句话总结:可以用hasClass方法(专用)和is方法 1.is(expr|obj|ele|fn)的方法几个参数表示什么 ...
- Elasticsearch之源码分析(shard分片规则)
前期博客是 Elasticsearch之源码编译 (1)elasticsearch在建立索引时,根据id或(id,类型)进行hash,得到hash值之后再与该索引的分片数量取模,取模的值即为存入的分片 ...