题目
分析
点分治。
点分治入门题,首先这题可以直接做,也可以转化成 "小于等于 (k) 的减掉 小于等于 (k-1) 的" ,然后相减来做。
两者皆可。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
inline int inc(int x,int v,int mod){x+=v;return x>=mod?x-mod:x;}
inline int dec(int x,int v,int mod){x-=v;return x<0?x+mod:x;}
inline int read(){int x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
inline void write(int x){if(x==0){putchar(48);return;}int len=0,dg[20];while(x>0){dg[++len]=x%10;x/=10;}for(register int i=len;i>=1;i--)putchar(dg[i]+48);}
const int N=1e5+5;
const int M=1e7+5;
struct node{
int to,next,val;
}edge[1000005];
int used[N],head[N],idy,q[N],maxson[N],tot,size[N],dis[N],rev[N],cnt;
bool vis[N],ans[N],rvis[M];
int n,m,id,idx;
void add(int u,int v,int w){
edge[++idx].to=v;
edge[idx].next=head[u];
edge[idx].val=w;
head[u]=idx;
return ;
}
void dfs(int x,int fa){
size[x]=1;
maxson[x]=0;
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(y==fa||vis[y])continue;
dfs(y,x);
size[x]+=size[y];
maxson[x]=max(maxson[x],size[y]);
}
maxson[x]=max(maxson[x],tot-size[x]);
if(maxson[x]<maxson[id])id=x;
return ;
}
void dist(int x,int fa){
rev[++cnt]=dis[x];
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(y==fa||vis[y])continue;
dis[y]=dis[x]+edge[i].val;
dist(y,x);
}
}
void calc(int x){
idy=0;
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(vis[y])continue;
cnt=0;
dis[y]=edge[i].val;
dist(y,x);
for(int j=1;j<=cnt;j++){
for(int k=1;k<=m;k++){
if(q[k]-rev[j]>=0&&q[k]-rev[j]<=1e7 && rvis[q[k]-rev[j]])ans[k]=1;
}
}
for(int j=1;j<=cnt;j++) if(rev[j]<=1e7)used[++idy]=rev[j],rvis[rev[j]]=1;
}
for(int i=1;i<=idy;i++)rvis[used[i]]=0;
}
void solve(int x){
vis[x]=rvis[0]=1;
calc(x);
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(vis[y])continue;
id=0;
maxson[id]=tot=size[y];
dfs(y,0);
solve(id);
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=n-1;i++){
int x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
for(int i=1;i<=m;i++)q[i]=read();
maxson[id]=tot=n;
dfs(1,0);
solve(id);
for(int i=1;i<=m;i++){
printf("%s
",(ans[i]||(!q[i])) ? "Yes" : "No");
}
return 0;
}
感受
这题第二种做法很巧妙,同样的办法在一道模拟题也见过,同样是容斥,但是那道题是 (dp) 。