BZOJ3510 首都

来源:互联网 发布:网络黑白txt下载免费 编辑:程序博客网 时间:2024/04/29 01:38

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

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

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

用LCT维护子树大小即可

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

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<vector>#include<map>#include<set>#include<bitset>#include<queue>#include<stack>using namespace std;#define MAXN 100010#define MAXM 1010#define INF 1000000000#define MOD 1000000007#define eps 1e-8#define ll long longstruct 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<<son[i][0]<<' '<<son[i][1]<<' '<<fa[i]<<endl;}cerr<<"-------"<<endl;}inline void be(int x,int y){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;}inline void bde(int x,int y){be(x,y);be(y,x);}int FA(int x){return F[x]==x?x:F[x]=FA(F[x]);}inline bool ir(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}inline void cot(int x,int y,bool z){if(x){fa[x]=y;}if(y){son[y][z]=x;}}inline void torev(int x){if(!x){return ;}swap(son[x][0],son[x][1]);rev[x]^=1;}inline void ud(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+1+Siz[x];}inline void pd(int x){if(rev[x]){torev(son[x][0]);torev(son[x][1]);rev[x]=0;}}inline void rot(int x,bool z){int xx=fa[x],xxx=fa[xx];cot(son[x][z],xx,z^1);if(ir(xx)){fa[x]=xxx;}else{cot(x,xxx,son[xxx][1]==xx);}cot(xx,x,z);ud(xx);}inline void apd(int x){int i;st[++tp]=x;for(i=x;!ir(i);i=fa[i]){st[++tp]=fa[i];}for(;tp;tp--){pd(st[tp]);}}void splay(int x){apd(x);while(!ir(x)){int xx=fa[x],xxx=fa[xx];if(ir(xx)){rot(x,son[xx][0]==x);}else{bool z=son[xxx][0]==xx;if(son[xx][z]==x){rot(x,z^1);rot(x,z);}else{rot(xx,z);rot(x,z);}}}ud(x);}inline void acs(int x){int t=0;while(x){splay(x);Siz[x]+=siz[son[x][1]]-siz[t];son[x][1]=t;ud(x);t=x;x=fa[x];}}inline void reboot(int x){acs(x);splay(x);torev(x);}inline void link(int x,int y){reboot(x);reboot(y);fa[x]=y;Siz[y]+=siz[x];ud(y);reboot(rt[FA(y)]);acs(x);splay(rt[FA(y)]);int S=siz[rt[FA(y)]];int t=son[rt[FA(y)]][1];pd(t);while(son[t][0]){t=son[t][0];pd(t);}acs(t);if((Siz[t]+1)*2>S||(Siz[t]+1)*2==S&&t<rt[FA(y)]){xs^=rt[FA(y)];xs^=t;rt[FA(y)]=t;}}void dfs(int x,int f){int i,y;son[x][0]=son[x][1]=fa[x]=rev[x]=0;Siz[x]=0;siz[x]=1;link(x,f);for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if(y!=f){dfs(y,x);}}}int main(){int i,x,y;char o[5];scanf("%d%d",&n,&m);for(i=1;i<=n;i++){F[i]=i;rt[i]=i;siz[i]=SIZ[i]=1;xs^=i;}while(m--){scanf("%s",o);if(o[0]=='A'){scanf("%d%d",&x,&y);if(SIZ[FA(x)]>SIZ[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 9A 1 2A 3 4A 5 4A 4 6A 1 7A 1 8A 1 4A 3 9Q 1*/


1 0
原创粉丝点击