Codeforces Round #433 (Div. 2) D. Jury Meeting(思维 贪心 前后缀)

题意:有n+1个城市,从1~n号城市每个城市有一个评委要到0号城市和其他n-1个评委一起工作k天(这k天n个评委都要在),并且要把所有评委送回他原来所在的城市。现在有m个航班,只有从i号城市到0号城市,或者从0号城市到i号城市(航班到达的那天不能工作),问你最少需要花费多少钱。


思路:贪心维护dp1[i] 表示第i天所有评委到达的最小花费,dp2[i]表示第i天所有评委离开的花费. 处理完dp1,dp2后枚举一遍区间维护ans即可。


代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const ll INF = 0x3f3f3f3f3f3f3f3f-1;
struct node
{
    ll d, u, v, c;
    bool operator <(const node &a) const
    {
        return d < a.d;
    }
}a[maxn];
ll vis[maxn], dp1[maxn], dp2[maxn];

int main(void)
{
    int n, m, k;
    while(cin >> n >> m >> k)
    {
        for(int i = 1; i <= m; i++)
            scanf("%I64d%I64d%I64d%I64d", &a[i].d, &a[i].u, &a[i].v, &a[i].c);
        for(int i = 0; i < maxn; i++)
            vis[i] = -1, dp1[i] = INF;
        sort(a+1, a+1+m);
        ll num = 0, sum = 0;
        for(int i = 1; i <= m; i++)
        {
            if(a[i].u == 0) continue;
            if(vis[a[i].u] == -1)
                num++, vis[a[i].u] = a[i].c, sum += a[i].c;
            else
            {
                if(vis[a[i].u] > a[i].c)
                {
                    sum -= vis[a[i].u];
                    vis[a[i].u] = a[i].c;
                    sum += a[i].c;
                }
            }
            if(num == n)
                dp1[a[i].d] = sum;
        }
        num = sum = 0;
        for(int i = 0; i < maxn; i++)
            vis[i] = -1, dp2[i] = INF;
        for(int i = m; i >= 1; i--)
        {
            if(a[i].v == 0) continue;
            if(vis[a[i].v] == -1)
                num++, vis[a[i].v] = a[i].c, sum += a[i].c;
            else
            {
                if(vis[a[i].v] > a[i].c)
                {
                    sum -= vis[a[i].v];
                    vis[a[i].v] = a[i].c;
                    sum += a[i].c;
                }
            }
            if(num == n)
                dp2[a[i].d] = sum;
        }
        for(int i = 1; i < maxn; i++)
            dp1[i] = min(dp1[i], dp1[i-1]);
        for(int i = maxn-2; i >= 1; i--)
            dp2[i] = min(dp2[i], dp2[i+1]);
        ll ans = INF;
        for(int i = 1; i+k+1 < maxn; i++)
            ans = min(ans, dp1[i]+dp2[i+k+1]);
        if(ans == INF) puts("-1");
        else printf("%I64d\n", ans);
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值