Codeforces854D【数据结构-线段树】

只要相差k天,然后来的航班取个小的,去的航班取个小的就是答案;
先维护去的航班第p天开始能使所有地点都能到达的最小值,拿线段树维护最小值,然后枚举来的航班得出答案。

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define lson num<<1,Left,Mid
#define rson num<<1|1, Mid+1, Right
typedef long long LL;
const LL INF = 1e18;
const int Maxn = 1e5 + 10;
struct asd{
    int d, f;
    LL w;
}node1[Maxn], node2[Maxn];
bool cmp(asd x, asd y){return x.d < y.d;}
int num1, num2;
LL s[Maxn*10], f[Maxn*10];
int n, m, k;
struct Seg{
    int Left, Right;
    LL Mi;
}node[Maxn*50];
void Build(int num, int Left, int Right){
    node[num].Left = Left;
    node[num].Right = Right;
    if(Left == Right){
        node[num].Mi = INF;
        return;
    }
    int Mid = (Left+Right)>>1;
    Build(lson);
    Build(rson);
    node[num].Mi = INF;
}

void Update(int num, int x, LL val){
    if(node[num].Left == node[num].Right){
        if(node[num].Left == x) node[num].Mi = min(node[num].Mi, val);
        return;
    }
    int Mid = (node[num].Left + node[num].Right) >> 1;
    if(Mid >= x) Update(num<<1, x, val);
    else Update(num<<1|1, x, val);
    node[num].Mi = min(node[num<<1].Mi, node[num<<1|1].Mi);
}

LL Query(int num, int s, int t){
    if(node[num].Left >= s && node[num].Right <= t)
        return node[num].Mi;
    int Mid = (node[num].Left + node[num].Right) >> 1;
    if(Mid >= t) return Query(num<<1, s, t);
    else if(Mid < s) return Query(num<<1|1, s, t);
    else return min(Query(num<<1, s, Mid), Query(num<<1|1, Mid+1, t));
}

int main(){
    int dd, ss, ff;
    LL ww;
    for(int i=1;i<=1000000;i++) s[i] = f[i] = -1;
    scanf("%d%d%d",&n,&m,&k);
    num1 = num2 = 0;
    for(int i=0;i<m;i++){
        scanf("%d%d%d%I64d",&dd,&ss,&ff,&ww);
        if(!ss){
            node2[num2] = (asd){dd, ff, ww};
            num2++;
        }
        else{
            node1[num1] = (asd){dd, ss, ww};
            num1++;
        }
    }
    sort(node1, node1+num1, cmp);
    sort(node2, node2+num2, cmp);
    Build(1, 1, 1000000);

    int Left = 0, Right = num2 - 1;
    int Left_num = 0, Right_num = 0;
    LL ans = 0;
    while(Right >= 0){
        if(f[node2[Right].f] == -1){
            f[node2[Right].f] = node2[Right].w;
            Right_num++;
            ans = ans + f[node2[Right].f];
        }
        else if(node2[Right].w < f[node2[Right].f]){
            ans = ans - f[node2[Right].f];
            f[node2[Right].f] = node2[Right].w;
            ans = ans + f[node2[Right].f];
        }
        if(Right_num == n) Update(1, node2[Right].d, ans);
        Right--;
    }
    ans = 0;
    LL res = INF, temp;
    while(Left < num1){
        if(s[node1[Left].f] == -1){
            s[node1[Left].f] = node1[Left].w;
            Left_num++;
            ans = ans + s[node1[Left].f];
        }
        else if(node1[Left].w < s[node1[Left].f]){
            ans = ans - s[node1[Left].f];
            s[node1[Left].f] = node1[Left].w;
            ans = ans + s[node1[Left].f];
        }
        if(Left_num == n){
            if((node1[Left].d + k + 1) < 1000000) temp = Query(1, node1[Left].d + k + 1, 1000000);
            if(temp != INF) res = min(ans + temp, res);
        }
        Left++;
    }
    if(res == INF) puts("-1");
    else printf("%I64d\n", res);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值