求助贪心做法:
发现大家都是暴力找的k祖先,于是写了长剖打算倍增找,然后#9-20都wa了
代码:
//#define LawrenceSivan
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define re register
const int maxn=2e5+5;
int n,k,t,ans;
int head[maxn],to[maxn<<1],nxt[maxn<<1],cnt;
inline void add(int u,int v){
nxt[++cnt]=head[u];
to[cnt]=v;
head[u]=cnt;
}
int fa[maxn][25],lg[maxn];
inline void pre_work(){
for(re int i=2;i<=n;i++){
lg[i]=lg[i>>1]+1;
}
}
int dep[maxn],szdep[maxn],son[maxn],top[maxn];
void dfs1(int u,int f){
fa[u][0]=f;
dep[u]=szdep[u]=dep[f]+1;
for(re int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==f)continue;
dfs1(v,u);
szdep[u]=max(szdep[u],szdep[v]);
if(szdep[v]>szdep[son[u]])son[u]=v;
}
}
int id[maxn],tot,up[maxn],down[maxn];
void dfs2(int u,int f){
id[u]=++tot;
down[tot]=u;
up[tot]=f;
if(!son[u])return;
top[son[u]]=top[u];
dfs2(son[u],fa[f][0]);
for(re int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==fa[u][0]||v==son[u])continue;
top[v]=v;
dfs2(v,v);
}
}
int query(int u,int kth){
if(!kth)return u;
u=fa[u][lg[kth]];
kth-=(1<<lg[kth]);
kth-=dep[u]-dep[top[u]];
u=top[u];
if(kth>=0)return up[id[u]+kth];
return down[id[u]-kth];
}
inline bool cmp(int a,int b){
return dep[a]>dep[b];
}
int f[maxn];
void update(int u,int fa,int dep){
f[u]=1;
if(dep==k)return;
for(re int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==fa)continue;
update(v,u,dep+1);
}
}
int pos[maxn];
inline int read(){
int x=0, f=1;char ch=getchar();
while (!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
int main() {
#ifdef LawrenceSivan
freopen("aa.in", "r", stdin);
freopen("aa.out", "w", stdout);
#endif
n=read();k=read();t=read();
for(re int i=1,u,v;i<n;i++){
u=read();v=read();
add(u,v);add(v,u);
}
pre_work();
dfs1(1,0);
dfs2(1,1);
for(re int i=1;i<=n;i++){
pos[i]=i;
}
sort(pos+1,pos+1+n,cmp);
for(re int i=1;i<=n;i++){
if(f[pos[i]])continue;
if(dep[pos[i]]<=k)update(1,0,0);
else {
int ancestor=query(pos[i],k);
update(ancestor,0,0);
}
ans++;
}
printf("%d\n",ans);
return 0;
}