0
点赞
收藏
分享

微信扫一扫

CF980E The Number Games 贪心+LCT

芥子书屋 2022-05-25 阅读 2

我们发现正着枚举删除哪些叶子是错的,但是贪心枚举留下哪些却是对的.  

我们枚举的时候需要动态查一个点到根有几个点没染色,和动态染色. 

支持这些操作的数据结构非 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;
}






举报

相关推荐

0 条评论