P4092 [HEOI2016/TJOI2016]树 题解
作者:互联网
Link
Solve
这道题是一个树剖显然能解决的问题,但是lyz神仙非要离线做懒得写树剖
考虑离线做,一个点把一条链分成两部分,比较类似于删边的操作,对于只有删边,我们就可以考虑倒过来处理,就只有连边了,用并查集来维护
如果最后是被标记过的点,把\(fa[]\)标为自己,否则标记为父节点。
反过来处理,如果询问,直接获取\(get(x)\)就是答案,如果是标记,就\(vis[x]--\),如果\(vis[x]\)被减到\(0\)了,说明这条链已经被打通了,就把\(fa[x]\)改为自己的父亲
还有一个细节,1号节点没有父节点,所以在\(vis[x]--\)的时候要注意一下
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005,maxe=200005;
int N,fa[maxn],Q,ans[maxn],lnk[maxn],cnt,nxt[maxe],son[maxe],vis[maxn],fa_tree[maxn];
struct query{
char op;
int x;
}q[maxn];
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline char read_ch(){
char ch=getchar();
while(ch!='C'&&ch!='Q')ch=getchar();
return ch;
}
inline void add_e(int x,int y){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;}
void DFS(int x,int f){
fa[x]=(vis[x]||x==1)?x:fa_tree[x];
for(int j=lnk[x];j;j=nxt[j]){
if(son[j]==f)continue;
fa_tree[son[j]]=x;
DFS(son[j],x);
}
return ;
}
int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
int main(){
freopen("P4092.in","r",stdin);
freopen("P4092.out","w",stdout);
N=read();Q=read();
for(int i=1;i<N;i++){
int x=read(),y=read();
add_e(x,y);add_e(y,x);
}
for(int i=1;i<=Q;i++){
q[i].op=read_ch();q[i].x=read();
if(q[i].op=='C')vis[q[i].x]++;
}
DFS(1,0);vis[1]++;
for(int i=Q;i;i--){
if(q[i].op=='C'){
if(!--vis[q[i].x])fa[q[i].x]=fa_tree[q[i].x];
}
else {
ans[++ans[0]]=get(q[i].x);
}
}
for(int i=ans[0];i;i--)printf("%d\n",ans[i]);
return 0;
}
标签:ch,vis,int,题解,son,P4092,fa,maxn,TJOI2016 来源: https://www.cnblogs.com/martian148/p/13910585.html