BZOJ 1460 Pku2114 Boatherds
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 1460 Pku2114 Boatherds
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
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
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的BZOJ 1460 Pku2114 Boatherds的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uda 3.C++二维向量
- 下一篇: 开源方案搭建可离线的精美矢量切片地图服务