Noip2015 运输计划 树上差分 二分答案
Posted guangheli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Noip2015 运输计划 树上差分 二分答案相关的知识,希望对你有一定的参考价值。
Code:
#include<cstring> #include<cstdio> #include<algorithm> #include<string> using namespace std; void setIO(string a){freopen((a+".in").c_str(),"r",stdin);} #define maxn 300090 #define logn 20 int head[maxn],to[maxn<<1],nex[maxn<<1],val[maxn<<1]; int f[logn][maxn],maxv[logn][maxn],sumv[logn][maxn],dep[maxn],tot[maxn]; int edges,n,m,delta,flag, max_delta; struct Query{ int u,v,len,tag,lca; }query[maxn]; void addedge(int u,int v,int c){ nex[++edges]=head[u],head[u]=edges,to[edges]=v,val[edges]=c; } void dfs(int u,int fa,int depth,int c){ f[0][u]=fa,dep[u]=depth,sumv[0][u]=maxv[0][u]=c; for(int i=1;i<logn;++i){ f[i][u]=f[i-1][f[i-1][u]]; sumv[i][u]=sumv[i-1][u]+sumv[i-1][f[i-1][u]]; maxv[i][u]=max(maxv[i-1][u],maxv[i-1][f[i-1][u]]); } for(int v=head[u];v;v=nex[v]){ if(to[v]==fa)continue; dfs(to[v],u,depth+1,val[v]); } } int LCA(int a,int b,int &qmax,int &qsum){ qmax=qsum=0; if(dep[a]>dep[b])swap(a,b); if(dep[a]!=dep[b]) for(int i=logn-1;i>=0;--i) if(dep[f[i][b]]>=dep[a]) { qmax=max(qmax,maxv[i][b]); qsum+=sumv[i][b]; b=f[i][b]; } if(a==b)return a; for(int i=logn-1;i>=0;--i) if(f[i][a]!=f[i][b]){ qmax=max(qmax,max(maxv[i][a],maxv[i][b])); qsum+=(sumv[i][b]+sumv[i][a]); b=f[i][b],a=f[i][a]; } qmax=max(qmax,max(maxv[0][a],maxv[0][b])); qsum+=(sumv[0][a]+sumv[0][b]); return f[0][a]; } int release(int u,int fa){ int cur=tot[u]; for(int v=head[u];v;v=nex[v]){ if(to[v]==fa)continue; cur+=release(to[v],u); } if(cur>=delta&&sumv[0][u]>=max_delta) flag=1; return cur; } bool check(int tps){ delta=0,flag=0,max_delta=0; for(int i=1;i<=m;++i) { if(query[i].len-query[i].tag>tps) return false; if(query[i].len>tps) ++delta, max_delta=max(max_delta,query[i].len-tps); } if(delta==0) return true; memset(tot,0,sizeof(tot)); for(int i=1;i<=m;++i) if(query[i].len>tps){ int a=query[i].u,b=query[i].v; tot[a]++,tot[b]++; tot[query[i].lca]-=2; } release(1,0); return flag; } int main(){ //setIO("input"); scanf("%d%d",&n,&m); for(int i=1;i<n;++i){ int a,b,c; scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); } dfs(1,0,1,0); for(int i=1;i<=m;++i){ scanf("%d%d",&query[i].u,&query[i].v); query[i].lca=LCA(query[i].u,query[i].v,query[i].tag,query[i].len); } int l=0,r=1500000000,mid,ans=0; while(l<=r){ mid=(l+r)>>1; if(check(mid)) ans=mid,r=mid-1; else l=mid+1; } printf("%d",ans); return 0; }
以上是关于Noip2015 运输计划 树上差分 二分答案的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)