您的位置:首页 > 运维架构

[BZOJ3510][启发式合并][LCT维护子树信息]首都

2017-02-15 18:41 477 查看
题意略…(今天比较懒)

由于只有建造公路没有破环公路,所以可以用启发式合并保持操作数为log,暴力拆开小的联通块,用LCT插到大的联通块内,然后用LCT维护子树信息,具体看这里

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 300010

using namespace std;

int n,m,rt
,g
,Ans,x,y,tp;
char op;
int fa
,ch
[2],sz
,isz
,rev
,sta
,tot
,G
,cnt;
struct edge{
int t,nx;
}E[N<<3];

inline int isr(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline int isl(int x){return ch[fa[x]][1]==x;}

int fifa(int x){return rt[x]==x?x:(rt[x]=fifa(rt[x]));}

inline void upd(int x){
if(!x) return;
sz[x]=1+isz[x];
if(ch[x][0]) sz[x]+=sz[ch[x][0]];
if(ch[x][1]) sz[x]+=sz[ch[x][1]];
}

inline void pushdown(int x){
if(!(x&&rev[x])) return;
swap(ch[x][0],ch[x][1]);
if(ch[x][0]) rev[ch[x][0]]^=1;
if(ch[x][1]) rev[ch[x][1]]^=1;
rev[x]=0;
}

inline void rot(int x){
int y=fa[x],z=fa[y],lor=isl(x);
if(!isr(y)) ch[z][ch[z][1]==y]=x; fa[x]=z;
if(ch[y][lor]=ch[x][lor^1]) fa[ch[y][lor]]=y;
fa[ch[x][lor^1]=y]=x; upd(y); upd(x);
}

inline void splay(int x){
sta[tp=1]=x;
for(int i=x;!isr(i);i=fa[i]) sta[++tp]=fa[i];
for(;tp;--tp) pushdown(sta[tp]);
for(;!isr(x);rot(x)) if(!isr(fa[x])) rot(isl(x)^isl(fa[x])?x:fa[x]);
}

inline void access(int x){
int t=0;
for(;x;x=fa[x]){
splay(x);
isz[x]+=sz[ch[x][1]]-sz[t];
ch[x][1]=t;
t=x;
upd(x);
}
}

inline void reverse(int x){access(x); splay(x); rev[x]^=1;}
inline void link(int x,int y){
reverse(x);
reverse(y);
fa[x]=y;
isz[y]+=sz[x];
upd(y);
reverse(g[fifa(y)]);
access(x);
splay(g[fifa(y)]);
int S=sz[g[fifa(y)]],t=ch[g[fifa(y)]][1];pushdown(t);
while(ch[t][0]) pushdown(t=ch[t][0]);
access(t);
if((isz[t]+1)*2>S||((isz[t]+1)*2==S&&t<g[fifa(y)])){
Ans^=g[fifa(y)]^t;
g[fifa(y)]=t;
}
}

inline void reaD(int &x){
char Ch=getchar();x=0;
for(;Ch>'9'||Ch<'0';Ch=getchar());
for(;Ch>='0'&&Ch<='9';x=x*10+Ch-'0',Ch=getchar());
}

inline void InserT(int x,int y){
E[++cnt].t=y;E[cnt].nx=G[x];G[x]=cnt;
E[++cnt].t=x;E[cnt].nx=G[y];G[y]=cnt;
}

void dfs(int x,int f){
ch[x][0]=ch[x][1]=fa[x]=isz[x]=rev[x]=0;
sz[x]=1;
link(x,f);
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=f) dfs(E[i].t,x);
}

inline void merge(int x,int y){
tot[fifa(y)]+=tot[fifa(x)];
Ans^=g[fifa(x)];
rt[fifa(x)]=fifa(y);
dfs(x,y); InserT(x,y);
}

int main(){
reaD(n); reaD(m);
for(int i=1;i<=n;i++) rt[i]=i,g[i]=i,Ans^=i,tot[i]=1;
for(int i=1;i<=m;i++){
while((op=getchar())!='A'&&op!='Q'&&op!='X');
if(op=='X') printf("%d\n",Ans);
else if(op=='Q') reaD(x),printf("%d\n",g[fifa(x)]);
else{
reaD(x); reaD(y);
if(tot[fifa(x)]>tot[fifa(y)]) swap(x,y);
merge(x,y);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: