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;   
}

  

 

posted @ 2019-11-10 18:35  EM-LGH  阅读(114)  评论(0编辑  收藏  举报