Bzoj3510首都
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 100005
#define maxm 400005
using namespace std; int n,m,ans,vis[maxn],head,tot,now[maxn],prep[maxm],son_[maxm],fa[maxn],son[maxn][],size[maxn],add[maxn],list[maxn],tail;
bool rev[maxn]; bool which(int x){
return son[fa[x]][]==x;
} bool isroot(int x){
return son[fa[x]][]!=x&&son[fa[x]][]!=x;
} void insert_(int x,int y){
size[x]+=y,add[x]+=y;
} void pushdown(int x){
if (!x) return;
if (rev[x]){
rev[x]^=,swap(son[x][],son[x][]);
if (son[x][]) rev[son[x][]]^=;
if (son[x][]) rev[son[x][]]^=;
}
if (add[x]){
if (son[x][]) insert_(son[x][],add[x]);
if (son[x][]) insert_(son[x][],add[x]);
add[x]=;
}
} void relax(int x){
if (!isroot(x)) relax(fa[x]);
pushdown(x);
} void rotata(int x){
int y=fa[x],d=which(x),dd=which(y);
if (!isroot(y)) son[fa[y]][dd]=x; fa[x]=fa[y];
fa[son[x][d^]]=y,son[y][d]=son[x][d^];
fa[y]=x,son[x][d^]=y;
} void splay(int x){
relax(x);
while (!isroot(x)){
if (isroot(fa[x])) rotata(x);
else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
else rotata(x),rotata(x);
}
} void access(int x){
for (int p=;x;x=fa[x]){
splay(x);
son[x][]=p;
p=x;
}
} int succ(int x){
splay(x);
int y=son[x][];
for (pushdown(y);son[y][];y=son[y][],pushdown(y));
return y;
} int find_root(int x){
access(x);
splay(x);
while (son[x][]) x=son[x][];
return x;
} void insert(int x,int y){
tot++,prep[tot]=now[x],now[x]=tot,son_[tot]=y;
} void bfs(int x,int y){
int t;
head=,tail=,list[]=y,size[y]=,fa[y]=son[y][]=son[y][]=,vis[y]=m,add[y]=rev[y]=;
while (head<tail){
head++,t=list[head];
for (int i=now[t],so=son_[i];i;i=prep[i],so=son_[i]){
if (vis[so]!=m){
vis[so]=m,size[so]=,fa[so]=son[so][]=son[so][]=add[so]=rev[so]=,fa[so]=t;
list[++tail]=so;
}
}
}
for (int i=tail;i>=;i--){
t=list[i];
if (fa[t]) size[fa[t]]+=size[t];
}
} void make_root(int x){
access(x);
splay(x);
rev[x]^=;
} void merge(int x,int y){
int rx,ry,t;
rx=find_root(x),ry=find_root(y);
if (rx==ry) return;
if (size[rx]<size[ry]) swap(x,y),swap(rx,ry);
ans^=ry;
bfs(x,y),insert(x,y),insert(y,x),fa[y]=x;
access(x),splay(x),insert_(x,size[y]);
// access(ry),splay(rx),relax(ry);
access(ry);
for (;;){
t=succ(rx);
if (!t){
make_root(rx);
break;
}
if (size[t]*>size[rx]||(size[t]*==size[rx]&&t<rx)){
// son[t][0]=0;
swap(size[t],size[rx]),size[rx]=size[t]-size[rx];
ans^=rx,ans^=t,rx=t;
}else{
make_root(rx);
break;
}
}
} int main(){
freopen("capital.in","r",stdin);
freopen("capital.out","w",stdout);
char st[];
int u,v;
memset(vis,-,sizeof(vis));
scanf("%d%d",&n,&m),ans=;
tot=,memset(now,,sizeof(now));
memset(rev,,sizeof(rev));
memset(size,,sizeof(size));
for (int i=;i<=n;i++) add[i]=fa[i]=son[i][]=son[i][]=,size[i]=;
for (int i=;i<=n;i++) ans^=i;
while (m--){
scanf("%s",st+);
if (st[]=='X') printf("%d\n",ans);
else if (st[]=='Q') scanf("%d",&u),printf("%d\n",find_root(u));
else scanf("%d%d",&u,&v),merge(u,v);
}
return ;
}
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3510
题意:一个森林,要求维护每棵树的重心(多个重心取编号最小的那个),支持三个操作:
1. 连接两个节点(保证两个节点不在同一棵树中)。
2. 询问某个节点所在树的重心。
3. 询问所有树的重心编号的异或和。
关于重心有几个性质:
- 以重心为根,任意一个子树的节点个数<=总结点数/2,否则重心可向该子树方向转移。
- 设树中节点x的权值为该点到树中每个点的距离之和,则重心的权值最小。
- 两个树合并为一颗新树后,新树的重心一定在原来的两个重心之间唯一的路径上。
做法:考虑用lct动态维护树的重心,以原树中的重心做为原树根,
由于只有合并操作(合并节点x和y,sizex>sizey),可以考虑启发式合并,即把节点数少的那棵树(y所在树)暴力重建(一次BFS),接到另一棵树(x所在树)上,节点y所在树上的信息可在bfs过程中维护好,节点x所在的树的size信息会有什么变化呢,我们发现节点x到原x树重心的路径上size[i]会加上y树的总结点数,这就是用lct的缘故。接下来我们考虑如何维护新树的重心,并作为新树的根呢?根据重心的性质3,我们考虑暴力转移重心,由于是启发式合并,据说复杂度可靠,我们将原来的两个重心的路径放到同一棵splay中来,从x树中重心开始暴力转移,如果节点p的后继节点q,若(sizeq*2>sizep)or(sizeq*2=sizep&&q<p),则将重心从p转移至q点,最后将make_root(新重心),操作1得以解决。
对于操作2,用lct求该节点所在树的根即可,因为树根为重心。
对于操作3, 用ans维护即可,每次更新重心更新时更新ans。
Lct动态维护树的重心(Lct+启发式合并+暴力转移重心)。
Bzoj3510首都的更多相关文章
- BZOJ3510 首都(LCT)
即动态维护树的重心.考虑合并后的新重心一定在两棵树的重心的连线上.于是对每个点维护其子树大小,合并时在这条链的splay上二分即可.至于如何维护子树大小,见https://blog.csdn.net/ ...
- BZOJ3510 首都
题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...
- BZOJ3510首都(LCT)
Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从 ...
- bzoj3510 首都 LCT 维护子树信息+树的重心
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3510 题解 首先每一个连通块的首都根据定义,显然就是直径. 然后考虑直径的几个性质: 定义:删 ...
- Some Conclusions.
目录 DP 四边形不等式 数论 & 数学 数据结构 树链剖分 左偏树的性质及\(O(n)\)的构造 图论 树 二分图 竞赛图 平面图 双连通分量 字符串 后缀自动机 复杂度分析 没什么好写的. ...
- LCT维护子树信息
有些题目,在要求支持link-cut之外,还会在线询问某个子树的信息.LCT可以通过维护虚边信息完成这个操作. 对于LCT上每个节点,维护两个两sz和si,后者维护该点所有虚儿子的信息,前者维护该点的 ...
- 【BZOJ3510】首都 LCT维护子树信息+启发式合并
[BZOJ3510]首都 Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打 ...
- 洛谷P4299 首都(BZOJ3510)(LCT,树的重心,二分查找)
Update:原来的洛谷U21715已成坑qwq 已经被某位管理员巨佬放进公共题库啦!又可以多一个AC记录啦! 洛谷题目传送门 其实也可以到这里交啦 思路分析 动态维护树的重心 题目中说到国家的首都会 ...
- 【bzoj3510】首都 LCT维护子树信息(+启发式合并)
题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...
随机推荐
- Flex String转Date
在Flex中日期字符串转为Date类型,可以使用静态方法DateFormatter.parseDateString(str:String):Date方法. 该方法支持的字符串格式包括: YYYY-MM ...
- Html5 Egret游戏开发 成语大挑战(七)游戏逻辑和数据处理
本篇在前面的基础上,将进行逻辑的编码开发让游戏能够正式的玩起来,这里没有注重太多的体验细节,而是直接实现游戏的规则逻辑,将分成两个部分说明:数据处理和游戏逻辑. 初始化游戏数据 在前面的第五篇中,我们 ...
- Camera.Parameters 参数
public class Camera.Parameters extends Object java.lang.Object ↳ android.hardware.Camera.Paramete ...
- 80端口未占用,apache无法启动解决办法
网上很多关于apache无法启动的原因,新手遇到最多的是80端口被占用. 今天为了解决apache和tomcat端口共存问题,修改了httpd.conf的配置,由于增加位置没有做明显标识,重启apac ...
- NVelocity学习笔记一——linq2sql+NVelocity完整demo
(一)前言 刚刚进入新公司,看公司的项目,发现开发流程几乎和以前的完全不同,再看看页面布局竟然没有发现html.神马情况????一番探究发现使用了NVelocity模板引擎开发的.于是乎花了 ...
- C/C++实践笔记 003
数据结构与算法程序=数据结构+算法语言是一种工具语言工具(c,c++)--程序设计方法(面向过程.面向对象)——数据结构(二叉树.队列.栈.红黑树.链表……)——算法(快速排序算法.冒泡排序算法.选择 ...
- sql中去除重复的项
方法一:group by (取最小的id)select min(id) id,T from Table_1 group by T 方法二:union (不需要id)select T from Tab ...
- ASP.NET Web API 实现客户端Basic(基本)认证 之简单实现
优点是逻辑简单明了.设置简单. 缺点显而易见,即使是BASE64后也是可见的明文,很容易被破解.非法利用,使用HTTPS是一个解决方案. 还有就是HTTP是无状态的,同一客户端每次都需要验证. 实现: ...
- [BZOJ1528][POI2005]sam-Toy Cars(贪心)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1528 分析:这个贪心很好想,因为每次如果加入一种玩具,那么必须要删掉一种玩具,就变成了 ...
- Java微信公众号开发-外网映射工具配置
一.开发环境准备 1.一个微信公众号 2.外网映射工具(开发调试)如花生壳.ngrok工具 注:与微信对接的URL要具备以下条件a:在公网上能够访问 b:端口只支持80端口 这里使用ngrok.cc: ...