题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=1460

思路

点分治。

(题面居然不说询问的最大值为106106)

Naive的O(qnlog2n)O(qnlog2⁡n)算法(1):

对每次询问做一遍点分治,用two pointer查询v1+v2<=kv1+v2<=k且v1+v2>kv1+v2>k的v1,v2v1,v2的个数,加上排序单次查询就是O(nlogn)O(nlog⁡n)。

BZOJ会TLE吧。

常数大了点的O(qnlogn)O(qnlog⁡n)算法(2):

对每次询问做一遍点分治,用一个桶记录值为v1v1的个数,然后查询一下q−v2q−v2的值的个数。

BZOJ还是会TLE。

常数比较小的O(qnlogn)O(qnlog⁡n)算法(3):

在算法(2)的基础上,离线回答询问,不用对每次询问做一遍点分治,只需要总体上做一遍点分治就可以了。

BZOJ 1000ms AC。

O(n2logn)O(n2log⁡n)算法(4):

把所有路径长度都丢到桶里面,最后O(1)O(1)回答询问。

BZOJ 4000ms以上 AC。

代码

特别感谢yxc大佬的算法(1),(4)的代码

算法(1)

#include<cstdio>
#include<algorithm>
#define il inline
#define rg register
#define N 10001
using namespace std;
struct fk{int to,w,nxt;}e[N<<1];
int n,k,p,root,Max,ans,dis[N],top;
int sz[N],maxv[N],head[N],cnt,vis[N];
il int read()
{char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+ch-'0';return x*f;
}
il void add(int u,int v,int w){e[++cnt].to=v;e[cnt].nxt=head[u];e[cnt].w=w;head[u]=cnt;}
il void get_size(int u,int fa)
{sz[u]=1;maxv[u]=0;for(rg int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa&&!vis[e[i].to])get_size(e[i].to,u),sz[u]+=sz[e[i].to],maxv[u]=max(maxv[u],sz[e[i].to]);
}
il void get_root(int r,int u,int fa)
{maxv[u]=max(maxv[u],sz[r]-sz[u]);if(Max>maxv[u])Max=maxv[u],root=u;for(rg int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa&&!vis[e[i].to])get_root(r,e[i].to,u);
}
il void get_dis(int u,int fa,int d)
{dis[++top]=d;for(rg int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa&&!vis[e[i].to])get_dis(e[i].to,u,d+e[i].w);
}
il int calc(int rt,int d)
{top=0;get_dis(rt,0,d);sort(dis+1,dis+top+1);int l=1,r=top,ret1=0,ret2=0;while(l<r){while(dis[l]+dis[r]>k&&l<r)r--;ret1+=r-l;l++;}l=1,r=top;while(l<r){while(dis[l]+dis[r]>=k&&l<r)r--;ret2+=r-l;l++;}return ret1-ret2;
}
il void dfs(int u)
{Max=n;get_size(u,0);get_root(u,u,0);int rt=root;ans+=calc(rt,0);vis[rt]=1;for(rg int i=head[rt];i;i=e[i].nxt)if(!vis[e[i].to])ans-=calc(e[i].to,e[i].w),dfs(e[i].to);
}
int main()
{n=read(),p=read();for(int i=1,u,v,w;i<n;i++)u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w);while(p--){k=read();if(k==0){puts("Yes");continue;}dfs(1);printf(ans>0?"Yes\n":"No\n");for(rg int i=1;i<=n;i++)vis[i]=0;ans=0;}
}

算法(2)

#include <cstdio>
#include <cstring>
#include <algorithm>const int maxn=10000;
const int maxp=100;
const int maxv=1000000;
const int inf=0x3f3f3f3f;int read()
{int x=0,f=1;char ch=getchar();while((ch<'0')||(ch>'9')){if(ch=='-'){f=-f;}ch=getchar();}while((ch>='0')&&(ch<='9')){x=x*10+ch-'0';ch=getchar();}return x*f;
}int pre[maxn*2+10],now[maxn+10],son[maxn*2+10],tot,val[maxn*2+10];
int vis[maxn+10],f[maxn+10],size[maxn+10],n,p,bin[maxv+10];
int q,nowroot,nowsize,cnt,tmp[maxn+10],flag,deep[maxn+10];int ins(int a,int b,int c)
{pre[++tot]=now[a];now[a]=tot;son[tot]=b;val[tot]=c;return 0;
}int getc(int u,int fa)
{size[u]=1;f[u]=0;int j=now[u];while(j){int v=son[j];if((v!=fa)&&(!vis[v])){getc(v,u);size[u]+=size[v];f[u]=std::max(f[u],size[v]);}j=pre[j];}f[u]=std::max(f[u],nowsize-size[u]);if(f[u]<f[nowroot]){nowroot=u;}return 0;
}int getdeep(int u,int fa)
{tmp[++cnt]=deep[u];int j=now[u];while(j){int v=son[j];if((v!=fa)&&(!vis[v])){deep[v]=deep[u]+val[j];getdeep(v,u);}j=pre[j];}return 0;
}int calc(int u,int ud)
{deep[u]=ud;cnt=0;getdeep(u,0);memset(bin,0,sizeof bin);int res=0;for(int i=1; i<=cnt; ++i){++bin[tmp[i]];}for(int i=1; i<=cnt; ++i){if(q>=tmp[i]){res+=bin[q-tmp[i]];}}return res>>1;
}int solve(int u)
{vis[u]=1;int ans=calc(u,0),j=now[u];while(j){int v=son[j];if((!vis[v])&&(!flag)){ans-=calc(v,val[j]);nowroot=0;nowsize=size[v];getc(v,0);solve(nowroot);}j=pre[j];}if(ans>0){flag=1;}return 0;
}int main()
{n=read();p=read();for(int i=1; i<n; ++i){int a=read(),b=read(),c=read();ins(a,b,c);ins(b,a,c);}f[0]=inf;while(p--){memset(vis,0,sizeof vis);q=read();flag=0;nowsize=n;nowroot=0;getc(1,0);solve(nowroot);if(flag){puts("Yes");}else{puts("No");}}return 0;
}

算法(3)

#include <cstdio>
#include <cstring>
#include <algorithm>const int maxn=10000;
const int maxp=100;
const int maxv=1000000;
const int inf=0x3f3f3f3f;int read()
{int x=0,f=1;char ch=getchar();while((ch<'0')||(ch>'9')){if(ch=='-'){f=-f;}ch=getchar();}while((ch>='0')&&(ch<='9')){x=x*10+ch-'0';ch=getchar();}return x*f;
}int pre[maxn*2+10],now[maxn+10],son[maxn*2+10],tot,val[maxn*2+10];
int vis[maxn+10],f[maxn+10],size[maxn+10],n,p,bin[maxv+10];
int q[maxn+10],ans[maxn+10],nowroot,nowsize,cnt,tmp[maxn+10],flag,deep[maxn+10];int ins(int a,int b,int c)
{pre[++tot]=now[a];now[a]=tot;son[tot]=b;val[tot]=c;return 0;
}int getc(int u,int fa)
{size[u]=1;f[u]=0;int j=now[u];while(j){int v=son[j];if((v!=fa)&&(!vis[v])){getc(v,u);size[u]+=size[v];f[u]=std::max(f[u],size[v]);}j=pre[j];}f[u]=std::max(f[u],nowsize-size[u]);if(f[u]<f[nowroot]){nowroot=u;}return 0;
}int getdeep(int u,int fa)
{if(deep[u]>maxv){return 0;}tmp[++cnt]=deep[u];int j=now[u];while(j){int v=son[j];if((v!=fa)&&(!vis[v])){deep[v]=deep[u]+val[j];getdeep(v,u);}j=pre[j];}return 0;
}int calc(int u,int ud,int op)
{deep[u]=ud;cnt=0;getdeep(u,0);for(int i=1; i<=cnt; ++i){++bin[tmp[i]];}for(int k=1; k<=p; ++k){int nq=q[k],res=0;for(int i=1; i<=cnt; ++i){if(nq>=tmp[i]){res+=bin[nq-tmp[i]];if(nq==(tmp[i]<<1)){++res;}}}ans[k]+=op*(res>>1);}for(int i=1; i<=cnt; ++i){--bin[tmp[i]];}return 0;
}int solve(int u)
{vis[u]=1;calc(u,0,1);int j=now[u];while(j){int v=son[j];if(!vis[v]){calc(v,val[j],-1);nowroot=0;nowsize=size[v];getc(v,0);solve(nowroot);}j=pre[j];}return 0;
}int main()
{n=read();p=read();for(int i=1; i<n; ++i){int a=read(),b=read(),c=read();ins(a,b,c);ins(b,a,c);}f[0]=inf;for(int i=1; i<=p; ++i){q[i]=read();}flag=0;nowsize=n;nowroot=0;getc(1,0);solve(nowroot);for(int i=1; i<=p; ++i){if((q[i]==0)||(ans[i]>0)){puts("Yes");}else{puts("No");}}return 0;
}

算法(4)

#include<cstdio>
#include<algorithm>
#include<iostream>
#define il inline
#define rg register
#define N 10001
using namespace std;
struct fk{int to,w,nxt;}e[N<<1];
int n,k,p,root,Max,ans,dis[N],top;
int sz[N],maxv[N],head[N],cnt,vis[N],sum[1000001];
il int read()
{char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+ch-'0';return x*f;
}
il void add(int u,int v,int w){e[++cnt].to=v;e[cnt].nxt=head[u];e[cnt].w=w;head[u]=cnt;}
il void get_size(int u,int fa)
{sz[u]=1;maxv[u]=0;for(rg int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa&&!vis[e[i].to])get_size(e[i].to,u),sz[u]+=sz[e[i].to],maxv[u]=max(maxv[u],sz[e[i].to]);
}
il void get_root(int r,int u,int fa)
{maxv[u]=max(maxv[u],sz[r]-sz[u]);if(Max>maxv[u])Max=maxv[u],root=u;for(rg int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa&&!vis[e[i].to])get_root(r,e[i].to,u);
}il void get_dis(int u,int fa,int d)
{dis[++top]=d;for(rg int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa&&!vis[e[i].to]&&d+e[i].w<=1e6)get_dis(e[i].to,u,d+e[i].w);
}
il void calc(int rt,int d,int t)
{top=0;get_dis(rt,0,d);sort(dis+1,dis+top+1);for(int i=1;i<=top;i++)for(int j=i+1;j<=top;j++){if(dis[i]+dis[j]>1e6)break;sum[dis[i]+dis[j]]+=t?1:-1;}
}
il void dfs(int u)
{Max=n;get_size(u,0);get_root(u,u,0);int rt=root;calc(rt,0,1);vis[rt]=1;for(rg int i=head[rt];i;i=e[i].nxt)if(!vis[e[i].to])calc(e[i].to,e[i].w,0),dfs(e[i].to);
}
int main()
{n=read(),p=read();for(int i=1,u,v,w;i<n;i++)u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w);dfs(1);while(p--){k=read();if(k==0){puts("Yes");continue;}printf(sum[k]?"Yes\n":"No\n");}
}

转载于:https://www.cnblogs.com/Canopus-wym/p/10376179.html

BZOJ 1460 Pku2114 Boatherds相关推荐

  1. BZOJ1460: Pku2114 Boatherds

    题目链接:点这里 题目描述:给你一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No. 数据范围:\(n\le1e5\,,p\le100\,,长 ...

  2. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  3. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  4. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

  5. BZOJ 2957楼房重建

    传送门 线段树 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include< ...

  6. BZOJ 2440: [中山市选2011]完全平方数 [容斥原理 莫比乌斯函数]

    2440: [中山市选2011]完全平方数 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3028  Solved: 1460 [Submit][S ...

  7. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  8. bzoj 4871: [Shoi2017]摧毁“树状图”

    4871: [Shoi2017]摧毁"树状图" Time Limit: 25 Sec  Memory Limit: 512 MB Submit: 53  Solved: 9 [Su ...

  9. BZOJ 1592. Making the Grade(思维,数据结构优化DP,以及三个拓展问题)[Usaco2008 Feb]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ简单题合集x 目录 BZOJ 1592. Making the Grade 拓展问题一 拓展问 ...

最新文章

  1. gis中的擦除_擦除—帮助 | ArcGIS for Desktop
  2. 全栈技术实践经历告诉你:开发一个商城小程序要多少钱?
  3. 第十四节: 介绍四大并发集合类并结合单例模式下的队列来说明线程安全和非安全的场景及补充性能调优问题。...
  4. Linux扩展SWAP分区
  5. 前后端项目中跨域问题
  6. java程序结构_Java 程序结构说明(学习 Java 编程语言 004)
  7. 程序员如何自我学习和成长?深度好文
  8. java双缓存机制_详解JVM类加载机制及类缓存问题的处理方法
  9. python 在线培训费用-python培训费需要多少钱?
  10. Qt-网易云音乐界面实现-3 音乐名片模块的实现
  11. 1.1 Linux系统概述、安装与体验
  12. linux安装unity桌面环境,Ubuntu 14.04 server安装桌面环境
  13. Android开发案例 点击按钮出现 简易的消息提示框
  14. html5数字在线处理,Qunee for HTML5 - 中文 : 事件处理
  15. 小米wifi如何设置虚拟服务器,小米路由器无线中继模式(桥接)用手机怎么设置? | 192路由网...
  16. E1630加工散热孔:中兴路由器wifi6千兆E1630电信商企版Wi-Fi6路由器3000M全千兆
  17. 什么是OCR?如何使用OCR文字识别软件?
  18. 传感器实验——SHT20温湿度传感器
  19. Fortran common
  20. 网络传输数据基本流程 详解

热门文章

  1. boost::hof::apply_eval用法的测试程序
  2. boost::hana::greater_equal用法的测试程序
  3. boost::function_types::is_member_function_pointer的用法测试程序
  4. Boost:测试使用大小为0的类array <>特化
  5. ITK:图像的区域最大值
  6. DCMTK:测试字符串OFString实用程序
  7. VTK:可视化之Blow
  8. VTK:图片之ImageConvolve
  9. OpenCV模板匹配Template Matching
  10. C语言在二叉搜索树找到第k个最小元素(附完整源码)