BZOJ 3319: 黑白树 树+并查集+未调完+神题
Code:
#include<bits/stdc++.h>
#define maxn 1000003
using namespace std;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c=='-') f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
void setIO(string s)
{
string in=s+".in", out=s+".out";
freopen(in.c_str(),"r",stdin);
freopen(out.c_str(),"w",stdout);
}
int n,Q,edges;
int hd[maxn],to[maxn<<1],nex[maxn<<1],val[maxn<<1],fa[maxn],dep[maxn],p[maxn],mark[maxn],tag[maxn];
int pd[maxn], answer[maxn];
void Init()
{
for(int i=0;i<maxn;++i) p[i]=i;
}
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
void addedge(int u,int v,int c)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
}
void dfs(int u,int ff)
{
fa[u]=ff;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff) continue;
dep[v]=dep[u]+1;
mark[v]=val[i];
dfs(v,u);
}
}
struct OPT
{
int o,u,v;
}opt[maxn];
void _2(int u,int v,int cur)
{
u=find(u),v=find(v);
while(u!=v)
{
// v is deeper than u
if(dep[u] > dep[v]) swap(u,v);
if(!pd[v]) p[v]=find(fa[v]), pd[v]=cur;
// printf("%d %d\n",dep[u],dep[v]);
v = p[v];
}
}
//set u -> v to white
void solve(int u,int v,int cur)
{
u=find(u),v=find(v);
while(u!=v)
{
if(dep[u] > dep[v]) swap(u,v);
if(pd[v]==cur) p[v]=find(fa[v]);
v = p[fa[v]]; // 暴力跳QAQ......
//v=p[v];
}
}
int main()
{
// setIO("input");
// scanf("%d%d",&n,&Q);
n=rd(),Q=rd();
for(int i=1;i<n;++i)
{
int u,v;
u=rd(),v=rd();
//scanf("%d%d",&u,&v);
addedge(u,v,i);
addedge(v,u,i);
}
dep[1]=1;
dfs(1,0);
for(int i=1;i<=Q;++i)
{
opt[i].o=rd();
//scanf("%d",&opt[i].o);
if(opt[i].o==1) opt[i].u=rd();
// scanf("%d",&opt[i].u);
else opt[i].u=rd(), opt[i].v=rd();
// scanf("%d%d",&opt[i].u,&opt[i].v);
}
// 处理黑点情况.
Init();
for(int i=1;i<=Q;++i)
{
if(opt[i].o==2) _2(opt[i].u,opt[i].v,i);
}
Init();
for(int i=2;i<=n;++i)
{
if(!pd[i]) //到最后也未被染成黑色 直接用并查集连上
{
int u = fa[i], v = i;
int x = find(u);
p[v] = x;
}
}
int tot = 0;
for(int i=Q;i>=1;--i)
{
if(opt[i].o==2)
{
//debug();
solve(opt[i].u, opt[i].v, i);
// debug();
}
else
{
int x = find(opt[i].u);
answer[++tot]=mark[x];
}
}
for(int i=tot;i>=1;--i) printf("%d\n",answer[i]);
return 0;
}