CF980E The Number Games 贪心+LCT
我们发现正着枚举删除哪些叶子是错的,但是贪心枚举留下哪些却是对的.
我们枚举的时候需要动态查一个点到根有几个点没染色,和动态染色.
支持这些操作的数据结构非 LCT 莫属
code:
#include <bits/stdc++.h> #define N 1000004 #define lson t[x].ch[0] #define rson t[x].ch[1] #define get(x) (t[t[x].f].ch[1]==x) #define isrt(x) (!(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x)) #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,edges,sta[N],ou[N],hd[N],to[N<<1],nex[N<<1]; void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } struct node { int f,ch[2],tag,size,sum,val; }t[N]; void pushup(int x) { t[x].size=t[lson].size+t[rson].size+1; t[x].sum=t[lson].sum+t[rson].sum+t[x].val; } void rotate(int x) { int old=t[x].f,fold=t[old].f,which=get(x); if(!isrt(old)) t[fold].ch[t[fold].ch[1]==old]=x; t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old; t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold; pushup(old),pushup(x); } void mark(int x) { if(!x) return; t[x].tag=1,t[x].sum=t[x].size,t[x].val=1; } void pushdown(int x) { if(x&&t[x].tag) { if(lson) mark(lson); if(rson) mark(rson); t[x].tag=0; } } void splay(int x) { int v=0,u=x,fa; for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f; for(;v;--v) pushdown(sta[v]); for(u=t[u].f;(fa=t[x].f)!=u;rotate(x)) if(t[fa].f!=u) rotate(get(fa)==get(x)?fa:x); } void Access(int x) { for(int y=0;x;y=x,x=t[x].f) splay(x),rson=y,pushup(x); } void dfs(int u,int ff) { t[u].f=ff; for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff) dfs(to[i],u); pushup(u); } int main() { // setIO("input"); int i,j,k; scanf("%d%d",&n,&k); for(i=1;i<n;++i) { int x,y; scanf("%d%d",&x,&y),add(x,y),add(y,x); } dfs(n,0); ou[n]=1; int re=1; Access(n),splay(n),mark(n); for(i=n-1;i>=1;--i) { Access(i),splay(i); if(t[i].size-t[i].sum+re<=n-k) re+=t[i].size-t[i].sum,mark(i),ou[i]=1; } for(i=1;i<=n;++i) if(!ou[i]) printf("%d ",i); return 0; }