bzoj 4551[Tjoi2016&Heoi2016]树
这题可以用并查集做,一开始统计一下记录每个点被标记了几次,除了被标记过的点外,其他节点都与其父亲所在集合合并,然后倒着做,做的时候如果有节点标记次数变为了0,则将其与其父亲合并。
代码
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 #include<algorithm> 5 #define N 500100 6 using namespace std; 7 typedef long long ll; 8 int n,m,i,a,b,dp,p[N],pre[N],tt[N]; 9 int F[N],v[N],sum[N],f[N],ans[N],tot; 10 char typ[N]; 11 void link(int x,int y) 12 { 13 dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y; 14 } 15 void dfs(int x,int fa) 16 { 17 int i=p[x]; 18 F[x]=fa; 19 while (i) 20 { 21 if (tt[i]!=fa) 22 dfs(tt[i],x); 23 i=pre[i]; 24 } 25 } 26 int gf(int x) 27 { 28 int p=x,t; 29 while (p!=f[p]) p=f[p]; 30 while (x!=p) 31 { 32 t=f[x];f[x]=p;x=t; 33 } 34 return p; 35 } 36 int main() 37 { 38 scanf("%d%d",&n,&m); 39 for (i=1;i<n;i++) 40 { 41 scanf("%d%d",&a,&b); 42 link(a,b);link(b,a); 43 } 44 dfs(1,0); 45 sum[1]=1; 46 for (i=1;i<=m;i++) 47 { 48 scanf(" %c%d",&typ[i],&v[i]); 49 if (typ[i]=='C') 50 sum[v[i]]++; 51 } 52 for (i=1;i<=n;i++) f[i]=i; 53 for (i=1;i<=n;i++) if (!sum[i]) f[gf(i)]=gf(F[i]); 54 for (i=m;i>=1;i--) 55 { 56 if (typ[i]=='Q') 57 { 58 tot++;ans[tot]=gf(v[i]); 59 } 60 else 61 { 62 sum[v[i]]--; 63 if (sum[v[i]]==0) f[gf(v[i])]=gf(F[v[i]]); 64 } 65 } 66 for (i=tot;i>=1;i--) 67 printf("%d\n",ans[i]); 68 69 }