CF161D solution to a problem [point] Divide and Conquer

Topic links:

  CF:http://codeforces.com/contest/161/problem/D

  Luogu: https://www.luogu.org/problem/CF161D

Dotted rule bare title.

The key point is how to divide and conquer update the answer.

And steps to find root partition is simple.

This question requires the tree path of exactly the number K.

Then it may be smaller than the number of paths equal to K minus the number of paths is less than K.

The other is very routine.

code show as below:

#include<bits/stdc++.h>
using namespace std;
const int maxn=50010;
struct node{
    int nxt,to,dis;
    #define nxt(x) e[x].nxt
    #define to(x) e[x].to
    #define dis(x) e[x].dis
}e[maxn<<1];
int head[maxn],tot,n,k;
inline void add(int from,int to,int dis){
    to(++tot)=to;dis(tot)=dis;
    nxt(tot)=head[from];head[from]=tot;
}
int maxp[maxn],siz[maxn],vis[maxn],sum,rt;
inline void getrt(int now,int fa){
    siz[now]=1;maxp[now]=0;
    for(int i=head[now];i;i=nxt(i)){
        int to=to(i);
        if(vis[to]||to==fa) continue;
        getrt(to,now);
        siz[now]+=siz[to];
        maxp[now]=max(maxp[now],siz[to]);
    }
    maxp[now]=max(maxp[now],sum-siz[now]);
    if(maxp[now]<maxp[rt]) rt=now;
}
int re[maxn],dep[maxn],cnt;
long long ans=0;
inline void getdis(int now,int fa){
    re[++cnt]=dep[now];
    for(int i=head[now];i;i=nxt(i)){
        int to=to(i);
        if(to==fa||vis[to]) continue;
        dep[to]=dep[now]+dis(i);
        getdis(to,now);
    }
}
inline int calc(int now,int w){
    cnt=0;dep[now]=w;
    getdis(now,0);
    sort(re+1,re+1+cnt);
    int l=1,r=cnt,res=0;
    while(l<r){
        if(re[l]+re[r]<=k) res+=(r-l),l++;
        else r--;
    }
    l=1,r=cnt;
    while(l<r){
        if(re[l]+re[r]<k) res-=(r-l),l++;
        else r--;
    }
    return res;
}
inline void solve(int now){
    ans+=calc(now,0);vis[now]=1;
    for(int i=head[now];i;i=nxt(i)){
        int to=to(i);
        if(vis[to]) continue;
        ans-=calc(to,dis(i));
        rt=0;sum=siz[to];
        getrt(to,0);
        solve(rt);
    }
}
int main()
{
    scanf("%d%d",&n,&k);    
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v,1);add(v,u,1);
    }
    sum=maxp[0]=n;
    rt=0;
    getrt(1,0);
    solve(rt);
    printf("%I64d\n",ans);
    system("pause");
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/ChrisKKK/p/11441697.html