BZOJ3510 首都(LCT)
即动态维护树的重心。考虑合并后的新重心一定在两棵树的重心的连线上。于是对每个点维护其子树大小,合并时在这条链的splay上二分即可。至于如何维护子树大小,见https://blog.csdn.net/neither_nor/article/details/52979425。明明都看那么多题解说要注意pushdown,结果还是因为这个调了一年,心态爆炸。(下面代码复杂度可能是假的,因为dfs完没有splay叶子,反正也没人卡我就不管了)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
#define M 200010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
#define lself tree[tree[k].fa].ch[0]
#define rself tree[tree[k].fa].ch[1]
char getc(){char c=getchar();while (c<'A'||c>'Z') c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,ans;
struct data{int ch[],fa,rev,size_f,size;
}tree[N];
void up(int k){tree[k].size=tree[lson].size+tree[rson].size+tree[k].size_f+;}
void rev(int k){if (k) swap(lson,rson),tree[k].rev^=;}
void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=;}
bool isroot(int k){return lself!=k&&rself!=k;}
int whichson(int k){return rself==k;}
void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
void move(int k)
{
int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
tree[tree[k].ch[!p]].fa=fa,tree[fa].ch[p]=tree[k].ch[!p];
tree[k].ch[!p]=fa,tree[fa].fa=k;
up(fa),up(k);
}
void splay(int k)
{
push(k);
while (!isroot(k))
{
int fa=tree[k].fa;
if (!isroot(fa))
if (whichson(k)^whichson(fa)) move(k);
else move(fa);
move(k);
}
}
void access(int k)
{
for (int t=;k;t=k,k=tree[k].fa)
{
splay(k);
tree[k].size_f+=tree[rson].size;
rson=t;
tree[k].size_f-=tree[rson].size;
up(k);
}
}
void makeroot(int k){access(k),splay(k),rev(k);}
int findroot(int k){access(k),splay(k);for (;lson;k=lson) down(k);splay(k);return k;}
int dfs(int k,int s,int r)
{
if (!k) return n+;
down(k);
if (s-(tree[k].size-tree[lson].size+r)<=(s>>))
{
int x=dfs(rson,s,r);
if (x<=n) return x;else return k;
}
else return dfs(lson,s,r+tree[k].size-tree[lson].size);
}
int find(int k){down(k);if (rson) return find(rson);else return k;}
void link(int x,int y)
{
int p=findroot(x),q=findroot(y);ans^=p,ans^=q;
makeroot(y),access(x),splay(x),tree[y].fa=x;
tree[x].size_f+=tree[y].size,up(x);
makeroot(p),access(q),splay(q);int s=tree[q].size;
p=dfs(q,s,),splay(p);
if (tree[p].size-tree[tree[p].ch[]].size<=(s>>))
splay(q=find(tree[p].ch[])),p=min(p,q);
makeroot(p);ans^=p;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3510.in","r",stdin);
freopen("bzoj3510.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
for (int i=;i<=n;i++) ans^=i,tree[i].size=;
while (m--)
{
char c=getc();
if (c=='X') printf("%d\n",ans);
if (c=='A') link(read(),read());
if (c=='Q') printf("%d\n",findroot(read()));
}
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)
Description 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从 ...
- 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; ...
随机推荐
- java 容器 List
1.概念:Java容器类类库的用途是保存对象,容器中不能存储基本数据类型,必须是对象(引用数据类型) 2.为什么需要容器:主要是在以数组作为数据的存储结构中,其长度难以扩充,同时数组中元素类型必须相同 ...
- SourceInsight工具增强——AStyle(代码格式化)、PC-Lint(静态检查)
Artistic Style(AStyle) AStyle是一款开源.高效.精简的代码格式化工具,适用于C.C++.C#.Java等.官方地址在:http://astyle.sourceforge.n ...
- mysql 添加字段,未响应
ddl是要请求锁整个表的,肯定是这个表上有DML事务了,也就是有其它会话在删除.修改.插入这个表并且未提交
- electron 开发实时加载
第一个方式 cnpm install electron-reload --save-dev cnpm install electron-prebuilt --save-dev require('ele ...
- CF 888E Maximum Subsequence
一道比较套路的题,看到数据范围就差不多有想法了吧. 题目大意:给一个数列和\(m\),在数列任选若干个数,使得他们的和对\(m\)取模后最大 取膜最大,好像不能DP/贪心/玄学乱搞啊.\(n\le35 ...
- SKINNY加密算法详解(无代码,仅加密)
原作者论文请参考<The SKINNY Family of Block Ciphers and Its Low-Latency Variant MANTIS> 地址为:https://li ...
- linux-镜像下载
https://blog.csdn.net/sinat_36564972/article/details/81560395 Centos6.5镜像下载 2018年08月10日 11:35:53 深夜搬 ...
- JS中的跨域问题
一.什么是跨域? 1.定义:跨域是指从一个域名的网页去请求另一个域名的资源.比如从www.baidu.com 页面去请求 www.google.com 的资源.但是一般情况下不能这么做,它是由浏览器的 ...
- jeecg的下拉列表
jeecg里面下拉列表的使用 ①建立数据字典seo_id <t:dictSelect field="operationPromotionAccount" typeGroupC ...
- shiro课程的学习
1.shiro的课程目标 (1)shiro的整体框架 各组件的概念 (2)shiro 认证 授权的过程 (3)shiro自定义的Reaml Filter (4)shiro session 管理 (5) ...