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 运输计划 树上差分 二分答案的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2015运输计划(树上差分,二分答案)

BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)

运输计划(题解)(Noip2015)

洛谷 P2680 [NOIP2015 提高组] 运输计划(二分,树上查分,树上倍增,LCA)

BZOJ4326: NOIP2015 运输计划

[NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组