点分治模板

虽然说是一个模板题,但其实并不是那么模板……

数据加强之后,N^2的时间复杂度是过不了的。注意到m只有一百,考虑先输入m个数,离线处理。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=25000;
inline int read(){
    int x=0,f=1;
    char c=getchar();
    while(c>'9'||c<'0'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+c-'0';
        c=getchar();
    }
    return x*f;
}
int beg[maxn],nex[maxn],to[maxn],w[maxn],e;
void add(int x,int y,int z){
    e++;nex[e]=beg[x];
    beg[x]=e;to[e]=y;w[e]=z;
}
int n,m;
int mx,size,rt;
int sz[maxn],son[maxn];
int vis[maxn],ans[20000005],top,st[maxn];
inline void getrt(int x,int fa){
    sz[x]=1;son[x]=0;
    for(int i=beg[x];i;i=nex[i]){
        int t=to[i];
        if(t==fa||vis[t])continue;
        getrt(t,x);
        sz[x]+=sz[t];
        if(sz[t]>son[x])son[x]=sz[t];
    }
    if(size-sz[x]>son[x])son[x]=size-sz[x];
    if(son[x]<mx)mx=son[x],rt=x;
}
inline void query(int pos,int fa,int have){
    st[++top]=have;
    for(int i=beg[pos];i;i=nex[i]){
        int t=to[i];
        if(t==fa||vis[t])continue;
        query(t,pos,have+w[i]);
    }
}
int q[maxn],p,ask[maxn],test[maxn];
inline void solve(int pos){
    p=0;ans[0]=1;
    for(int i=beg[pos];i;i=nex[i]){
        int t=to[i];
        if(vis[t])continue;
        top=0;
        query(t,pos,w[i]);
        for(int j=top;j;j--)
            for(int k=1;k<=m;k++)
                if(ask[k]>=st[j])test[k]|=ans[ask[k]-st[j]];
        for(int j=1;j<=top;j++)
            q[++p]=st[j],ans[st[j]]=1;
    }
    for(int i=1;i<=p;i++)
        ans[q[i]]=0;
}
inline void devide(int x){
    vis[x]=1;
    solve(x);
    for(int i=beg[x];i;i=nex[i]){
        int t=to[i];
        if(vis[t])continue;
        mx=inf,size=sz[t],rt=0;
        getrt(t,0);
        devide(rt);
    }
}
int main(){
    n=read(),m=read();
    int x,y,z;
    for(int i=1;i<n;i++){
        x=read(),y=read(),z=read();
        add(x,y,z);
        add(y,x,z);
    }
    for(int i=1;i<=m;i++)
        ask[i]=read();
    mx=inf,size=n,rt=0;
    getrt(1,0);
    devide(rt);
    for(int i=1;i<=m;i++)
        puts(test[i]?"AYE":"NAY");
    return 0;
} 

请注意ans数组要尽量开大一点,不然会RE,QAQ。

posted @ 2020-02-29 22:45  syzf2222  阅读(89)  评论(0编辑  收藏  举报