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; ...
随机推荐
- Zephyr的Power Management
1 关于Zephyr Zephyr是Linux基金会维护的微内核项目,来源于WindRiver向Zephyr捐赠的Rocket RTOS内核.主要用于开发针对物联网设备的实时操作系统. Zephyr操 ...
- [06] JSTL标准标签库
1.JSTL概述 之前在<[03-01] JSP自定义标签>中已经说明了自定义标签的概况,而JSTL也是一套标签库,不过是厂商已经定义好的标签库,我们不再需要自行进行定制,直接使用即可. ...
- 源码分享篇:使用Python进行QQ批量登录
直接上源码 1 #coding=utf-8 2 __author__ = 'Eagle' 3 import os 4 import time 5 import win32gui 6 import wi ...
- Matplotlib 简单图例
图例参考:http://matplotlib.org/gallery.html API参考:http://matplotlib.org/api/pyplot_summary.html # -*- co ...
- Luogu3320 SDOI2015 寻宝游戏 链并
传送门 可以发现从哪里开始的最优答案都是一样的.我们只需要用一种比较好维护的方法维护答案就好了. 我们考虑用$dfs$序加上$set$维护链并.先预处理$dfs$序,将当前有宝藏的点丢入$set$中, ...
- POI Sax 事件驱动解析Excel2003文件
POI事件驱动解析Excel文件 package com.boguan.bte.util.excel; import java.io.FileInputStream; import java.io.I ...
- 记一次网页超时登录的Bug
前几天,在做全公司的员工测评工作,在一个页面弹出导入页面,并导入所有评价记录,然后关闭掉这个导入页面,最后返回当前页面,返回时刷新当前页面. 在返回的时候,就出现了“页面超时登录”同时返回登录首页的问 ...
- [Oracle][Partition][Controlfile]Partition 操作是否和 Controlfile有关?
Partition 操作是否和 Controlfile有关? 通过实验来判断: 对比 Partition 前后的操作,看看controlfile 的dump 信息中是否有记录,结果发现没有记录在 co ...
- linux awk 内置函数实例
awk内置函数,主要分4种:算数函数.字符串函数.时间函数.一般函数 一.算术函数 以下算术函数执行与 C 语言中名称相同的子例程相同的操作: 函数名 说明 atan2( y, x ) 返回 y/x ...
- Appium Studio 初体验(windows做ios自动化,录制appium脚本)
偶然的机会遇到了这个工具——Appium Studio, 在官网是这么解释的 Get your Appium testing projects going within minutesInstall ...