[HEOI2016/TJOI2016]樹
阿新 • • 發佈:2021-08-11
[HEOI2016/TJOI2016]樹
這是一道樹剖板子題,所以我們沒什麼講的
題解
我們用線段樹維護樹剖序上的\(sum\)值,即為染色的數量的\(sum\),當\(sum=0\)時,從\(x\)節點向上爬樹,當我們查詢到這條鏈的\(sum>=1\)時二分答案即可。
#include<bits/stdc++.h> using namespace std; const int MN=1e5+100; int n,q; int head[MN],cnt; struct node{ int nxt,to; }e[MN<<1]; inline void add(int a,int b){e[++cnt].nxt=head[a],head[a]=cnt,e[cnt].to=b;} int son[MN],siz[MN],fa[MN],dep[MN]; void dfs1(int now,int pre){ dep[now]=dep[pre]+1,fa[now]=pre,siz[now]=1; for(int i=head[now];i;i=e[i].nxt){ int to=e[i].to; if(to==pre)continue; dfs1(to,now); siz[now]+=siz[to]; if(siz[to]>siz[son[now]])son[now]=to; } } int dfn[MN],top[MN],tot,name[MN]; void dfs2(int now,int tp){ top[now]=tp,dfn[now]=++tot,name[tot]=now; if(son[now])dfs2(son[now],tp); for(int i=head[now];i;i=e[i].nxt){ int to=e[i].to; if(to==fa[now]||to==son[now])continue; dfs2(to,to); } } #define lc id<<1 #define rc id<<1|1 struct tree{ int l,r,sum; }t[MN<<2]; void pushup(int id){ t[id].sum=t[lc].sum+t[rc].sum; } void build(int id,int l,int r){ t[id].l=l,t[id].r=r; if(l==r)return; int mid=(l+r)>>1; build(lc,l,mid),build(rc,mid+1,r); } void change(int id,int k){ if(t[id].l==t[id].r&&t[id].l==k){ t[id].sum=1; return; } int mid=(t[id].l+t[id].r)>>1; if(k<=mid)change(lc,k); else change(rc,k); pushup(id); } int get_sum(int id,int l,int r){ if(t[id].l>=l&&t[id].r<=r)return t[id].sum; int mid=(t[id].l+t[id].r)>>1,ans=0; if(l<=mid)ans+=get_sum(lc,l,r); if(r>=mid+1)ans+=get_sum(rc,l,r); return ans; } int lower(int l,int r){ if(l==r)return name[l]; int mid=(l+r)>>1; if(get_sum(1,mid+1,r))return lower(mid+1,r); else return lower(l,mid); } int query(int x){ int ans=0; while(!ans){ int sum=0; sum=get_sum(1,dfn[top[x]],dfn[x]); if(sum){ ans=lower(dfn[top[x]],dfn[x]); } else x=fa[top[x]]; } return ans; } int main(){ freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); scanf("%d%d",&n,&q); for(int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u); dfs1(1,0);dfs2(1,1);build(1,1,n);change(1,dfn[1]); int x;char s; while(q--){ scanf("%s%d",&s,&x); if(s=='Q')printf("%d\n",query(x)); else change(1,dfn[x]); } return 0; }