BZOJ3510 首都

到所有点距离和最小的点就是重心

因为只有link操作,我们可以考虑启发式合并,这样最多会有n log n次“插入一个叶子节点”操作

一棵树插入一个叶子节点之后,重心要么不变,要么向叶子的方向移动一条边,移动的条件是叶子所在的子树大小*2大于这棵树的大小(或者相等取编号小的)

用LCT维护子树大小即可

有关LCT维护子树信息的讲解可以看这里

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXN 100010
#define MAXM 1010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
struct vec{
	int to;
	int fro;
};
vec mp[MAXN*2];
int tai[MAXN],cnt;
int fa[MAXN],son[MAXN][2],siz[MAXN],Siz[MAXN];
bool rev[MAXN];
int st[MAXN],tp;
int rt[MAXN];
int F[MAXN],SIZ[MAXN];
int xs;
int n,m;
void pt(){
	int i;
	for(i=1;i<=n;i++){
		cerr<S||(Siz[t]+1)*2==S&&tSIZ[FA(y)]){
				swap(x,y);
			}
			SIZ[FA(y)]+=SIZ[FA(x)];
			xs^=rt[FA(x)];
			F[FA(x)]=FA(y);
			dfs(x,y);
			bde(x,y);
		}
		if(o[0]=='Q'){
			scanf("%d",&x);
			printf("%d\n",rt[FA(x)]);
		}
		if(o[0]=='X'){
			printf("%d\n",xs);
		}
	}
	return 0;
}

/*
9 9
A 1 2
A 3 4
A 5 4
A 4 6
A 1 7
A 1 8
A 1 4
A 3 9
Q 1
*/


你可能感兴趣的:(BZOJ,LCT,启发式合并)