第一反应是dfs序+线段树,一个节点打上标记,就对整棵子树,下推标记时判断一下深度
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=100005; struct egde { int t,next; }e[N<<1]; struct tree { int ans; }tr[N<<2]; int cnt,n,m,num; int head[N],wei[N],law[N],dee[N]; void ans(int u,int t){ e[++cnt].t=t; e[cnt].next=head[u]; head[u]=cnt; } void build(int ts,int l,int r){ tr[ts].ans=0;tr[ts].ans=1; if (l==r) return; int mid=(l+r)>>1; build(ts<<1,l,mid); build(ts<<1|1,mid+1,r); } void dfs(int u,int fa){ wei[u]=++num;dee[u]=dee[fa]+1;; for (int i=head[u];i;i=e[i].next){ int v=e[i].t; if (v==fa) continue; dfs(v,u); } law[u]=num; } int get(int x,int y){return dee[x]>dee[y]?x:y;} void pushdown(int ts){ if (!tr[ts].ans) return; int k=tr[ts].ans;tr[ts].ans=0; tr[ts<<1].ans=get(k,tr[ts<<1].ans); tr[ts<<1|1].ans=get(k,tr[ts<<1|1].ans); } void update(int ts,int l,int r,int L,int R,int k){ if (l==L && r==R) { tr[ts].ans=get(k,tr[ts].ans); return; } int mid=(l+r)>>1; pushdown(ts); if (L>mid) update(ts<<1|1,mid+1,r,L,R,k); else if (R<=mid) update(ts<<1,l,mid,L,R,k); else { update(ts<<1,l,mid,L,mid,k);update(ts<<1|1,mid+1,r,mid+1,R,k); } } int query(int ts,int l,int r,int k){ if (l==r) return tr[ts].ans; int mid=(l+r)>>1; pushdown(ts); if (k<=mid) return query(ts<<1,l,mid,k); else return query(ts<<1|1,mid+1,r,k); } #define dd a=getchar() void read(char &a,int &b){ while(dd,a!='Q' && a!='C'); scanf("%d",&b); } #undef dd int main(){ // freopen("hh.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); ans(a,b);ans(b,a); } dfs(1,0); update(1,1,n,1,n,1); for (int i=1;i<=m;i++){ char a;int b; read(a,b); if (a=='Q') { printf("%d\n",query(1,1,n,wei[b])); } else { update(1,1,n,wei[b],law[b],b); } } }
F2:并查集,逆序操作,有标记的节点的父亲是自己,不然是父亲节点。每次查询找祖先,消节点改变父亲
#include <cstdio> using namespace std; const int N=100005; struct egde { int t,next; }e[N<<1]; struct quer{ int id,x; }qu[N]; int cnt,n,m; int head[N],mar[N],fa[N],f[N],ans[N]; void add(int u,int t){ e[++cnt].t=t; e[cnt].next=head[u]; head[u]=cnt; } void dfs(int u,int fa){ f[u]=fa; for (int i=head[u];i;i=e[i].next){ int v=e[i].t; if (v==fa) continue; dfs(v,u); } } int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} #define dd a=getchar() void read(char &a,int &b){ while(dd,a!='Q' && a!='C'); scanf("%d",&b); } #undef dd int main(){ // freopen("hh.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add(a,b);add(b,a); } dfs(1,1);mar[1]=1; for (int i=1;i<=m;i++){ char a;int b; read(a,b); if (a=='Q') { qu[i].id=0;qu[i].x=b; } else { mar[b]++; qu[i].id=1;qu[i].x=b; } } for (int i=1;i<=n;i++) if (!mar[i]) fa[i]=f[i]; else fa[i]=i; for (int i=m;i>=1;i--){ if (!qu[i].id) { ans[i]=find(qu[i].x); } else { mar[qu[i].x]--; if (!mar[qu[i].x]) fa[qu[i].x]=f[qu[i].x]; } } for (int i=1;i<=m;i++) if (!qu[i].id) printf("%d\n",ans[i]); }