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;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/9926525.html

时间: 2024-08-23 10:09:13

Noip2015 运输计划 树上差分 二分答案的相关文章

NOIp2015 运输计划 [LCA] [树上差分] [二分答案]

我太懒了 吃掉了题面 题解 & 吐槽 一道很好的树上差分练习题. 不加fread勉强a过bzoj和luogu的数据,加了fread才能在uoj里卡过去. 可以发现,答案则是运输计划里花费的最大值,最大值最小,便是二分答案的标志. 那么该怎么check呢... 我们得找出所有超过限制的计划,这个过程可以在LCA倍增的过程中预处理出来. 然后再找出一些被这些计划都覆盖的边,找到最大的那条边,如果最大的计划花费减去最大的那条边小于x,那么x就是可行的. 但是该怎么找到那些被计划都覆盖的边呢... 我们

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

[NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有星球. 小P掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从ui号星球沿最快的宇航路径飞行到vi号星球去.显然,飞船驶过一条航道是需要时间的,对于航道j,任意飞船驶过它所花费的时间为tj,并且任意两艘飞船之间不会产生任何干扰. 为了鼓励科技创新,L国国王同意小P的物流

【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分

4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 703  Solved: 461[Submit][Status][Discuss] Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui

NOIP2015 运输计划(二分+LCA+差分)

4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 308  Solved: 208[Submit][Status][Discuss] Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui

BZOJ 4326:NOIP2015 运输计划(二分+差分+lca)

NOIP2015 运输计划Description公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去.显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰.为了鼓励科技创新, L

树链剖分-Hello!链剖-[NOIP2015]运输计划-[填坑]

This article is made by Jason-Cow.Welcome to reprint.But please post the writer's address. http://www.cnblogs.com/JasonCow/ [NOIP2015]运输计划    Hello!链剖.你好吗? 题意: 给出一棵n个节点的带权树,m对树上点对 现在允许删除一条边,(权值修改为0) 输出: 最小化的点对间最大距离 1.链剖 2.树上差分 3.二分 链剖我就不多说了,就是两dfs 注意

AC日记——[NOIP2015]运输计划 cogs 2109

[NOIP2015] 运输计划 思路: 树剖+二分: 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 300005 #define INF 0x7fffffff int n,deep[maxn],dis[maxn],dis_[maxn],f[maxn],top[maxn]; i

数据结构(树链剖分):COGS 2109. [NOIP2015] 运输计划

2109. [NOIP2015] 运输计划 ★★★   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物 流飞船需要从 ui 号星球沿最快的宇航路径飞行到 v

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

题意:中文题. 析:首先二分是很容易想出来的,然后主要是判断这个解合不合法,先二分答案 mid,因为有 m 个计划,所以只要添加虫洞的肯定是所有的时间长于 mid 的计划 中,也就是是那些的共同边,这个就可以用树上差分来做了,假设 s 到 t,那么让in[s]++,in[t]++,in[lca(s, t)] -= 2,其中in 表示的是 该结点与其父结点的边的计数,最后再跑一次dfs,把所有的权值都累加上去,这样就能知道哪些是共同的边了. 代码如下: #pragma comment(linker