求助:关于长链剖分求树上k祖先
查看原帖
求助:关于长链剖分求树上k祖先
375208
LawrenceSivan楼主2021/6/30 09:11

求助贪心做法:

发现大家都是暴力找的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;
}

2021/6/30 09:11
加载中...