[模板]点分治

算法流程:找到树的重心,删去这个点,递归子树。
题号luogu3806

#include <iostream>
#include <ctime>
#include <algorithm>
#include <windows.h>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=10005;
inline int read(){
    int k=0,f=1; char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    return k*f;
}
int n,m,K,siz[N],head[N],ecnt,size,rt,cnt,a[150],f[N];
struct Edge{int to,nxt,val;}e[N<<1];
struct Node{int from,val; bool operator < (const Node &rhs) const {return val<rhs.val;};};
bool vis[N],ans[106];
Node dis[10005];
void add(int bg,int ed,int val){(++ecnt)[e].to=ed;ecnt[e].val=val;ecnt[e].nxt=bg[head];bg[head]=ecnt;}
int binary(int x) {
    int l=1,r=cnt,ans=0;
    while(l<=r) {
        int mid=l+r>>1;
        if(dis[mid].val<x) l=mid+1;
        else r=mid-1,ans=mid;
    }
    return ans;
}
void barycenter(int x,int fa) {
    f[x]=0,siz[x]=1;
    for(int i=head[x];i;i=e[i].nxt) {
        int v=e[i].to;
        if(vis[v]||fa==v) continue;
        barycenter(v,x);
        f[x]=max(f[x],siz[v]);
        siz[x]+=siz[v];
    }
    f[x]=max(f[x],size-siz[x]);
    if(f[x]<f[rt]) rt=x;
}
void dfs(int x,int fa,int from,int val) {
    dis[++cnt]={from,val};
    for(int i=head[x];i;i=e[i].nxt) {
        int v=e[i].to;
        if(vis[v]||fa==v) continue;
        dfs(v,x,from,val+e[i].val);
    }
}
void work(int x) {
    cnt=0;
    for(int i=x[head];i;i=i[e].nxt ) {
        int v=i[e].to;
        if(v[vis]) continue;
        dfs(v,x,v,e[i].val);
    }
    (++cnt)[dis]={0,0};
    sort(dis+1,dis+1+cnt);
    for(int i=1;i<=m;i++) {
        if(i[ans]) continue;
        int l=1;
        while(l<cnt&&a[i]>(dis[l].val+dis[cnt].val)) l++;
        while(l<cnt&&!ans[i]) {
            if(a[i]-dis[l].val<dis[l].val) break;
            int pos=binary(a[i]-dis[l].val);
            while(dis[pos].val+dis[l].val==a[i]&&l<=cnt&&dis[pos].from==dis[l].from) pos++;
            if(dis[pos].val+dis[l].val==a[i]) ans[i]=1;
            l++;
        }
    }
}
void solve(int x) {
    vis[x]=1;
    work(x);
    for(int i=head[x];i;i=e[i].nxt) {
        int v=e[i].to;rt=0;
        if(v[vis]) continue;
        siz[rt]=size=siz[v];
        barycenter(v,0);
        solve(rt);
    }
}
int main() {
    int st=clock();
    n=read();m=read();
    for(int i=1,x,y,z;i<n;i++)  x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
    for(int i=1;i<=m;i++) a[i]=read();
    f[rt]=size=n;
    barycenter(1,0);
    solve(rt);
    for(int i=1;i<=m;i++)puts(ans[i]?"AYE":"NAY");
    int ed=clock();
    Sleep(200);
    cout<<ed-st;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9475605.html