zoukankan      html  css  js  c++  java
  • 【Codeforces Round #433 (Div. 1) B】Jury Meeting

    【链接】h在这里写链接


    【题意】


    有n个人,它们都要在某一时刻开始,全都到达0位置,然后维持最少k个时间单位,然后再全都回到原来的位置;
    第i个人初始的位置是i.
    且一共有m班航班.
    每一班航班,要么是从0出来的,要么是进入0的,且航班起飞的时间为di,出发地为fi,目的地为ti,花费为ci;
    (航班当天到);
    到或起飞的那一天不算k天中的一天。
    问你每个人到达0,然后又回到各自位置的最小花费。

    【题解】


    考虑每个航班起飞的时间,把每个航班的信息加入到di时刻上.
    vector <pair <int,int> >in[N];
    存的是i时刻,进入0位置的飞机来自哪里,以及花费。
    vector <pair <int,int> >out[N];
    存的是i时刻,飞出0位置的飞机要到哪里,以及花费。
    然后O(N)顺着扫和逆着扫两遍。
    就能得到f1[i],num1[i];
    f1[i]表示前i个位置,有num1[i]个人能到0位置,最小的花费是多少.
    (时间顺序处理)
    以及f2[i],num2[i];
    f2[i]表示后n-i+1个位置,有num2[i]个人能回到原位置,最小的花费是多少;
    (时间逆序处理就好)
    以处理f1[i]为例。
    进入i+1时刻的时候,看看i+1这个时间,有多少个航班到位置0,然后,看看某个人来0位置的花费能不能因此变少
    (也即是不是那个人坐这班航班更优)
    如果可以因此变少的话,f1[i]也能变少.
    (如果那个人是第一次可以来0位置,那么num1[i]++)
    用一个mi[N]来维护某个人到达0位置的最小花费就可以了。
    (f2[i]用类似的方法维护就好)
    然后枚举这n个人是何时开始全都到达0号位置的
    f1[i]+f2[i+k+1]最小值就可以了;
    (num1[i]和num2[i+k+1]都必须为n);

    【错的次数】


    0

    【反思】


    感觉很自然的思路。

    【代码】

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e6;
    
    int n, m, k;
    vector <pair <int, int > > in[N + 10], out[N + 10];
    long long f1[N + 10], f2[N + 10];
    int num1[N + 10], num2[N + 10];
    int mi[N + 10], MI[N + 10];
    
    int main() {
        ios::sync_with_stdio(0), cin.tie(0);
    
        cin >> n >> m >> k;
        for (int i = 1; i <= m; i++) {
            int d, f, t, c;
            cin >> d >> f >> t >> c;
            if (t == 0)
                in[d].push_back(make_pair(f, c));
            else {
                //f == 0
                out[d].push_back(make_pair(t, c));
            }
        }
    
        for (int i = 1; i <= N; i++) {
            num1[i] = num1[i - 1];
            f1[i] = f1[i - 1];
            for (int j = 0; j <= (int)in[i].size() - 1; j++) {
                int from = in[i][j].first, cost = in[i][j].second;
                if (mi[from] == 0) {
                    mi[from] = cost;
                    num1[i]++;
                    f1[i] += cost;
                }
                else {
                    if (mi[from] > cost) {
                        f1[i] -= (mi[from] - cost);
                        mi[from] = cost;
                    }
                }
            }
        }
    
        for (int i = N; i >= 1; i--) {
            f2[i] = f2[i + 1];
            num2[i] = num2[i + 1];
            for (int j = 0; j <= (int)out[i].size() - 1; j++){
                int to = out[i][j].first; int cost = out[i][j].second;
                if (MI[to] == 0) {
                    MI[to] = cost;
                    f2[i] += cost;
                    num2[i]++;
                }
                else {
                    if (MI[to] > cost) {
                        f2[i] -= (MI[to] - cost);
                        MI[to] = cost;
                    }
                }
            }
        }
    
        long long ans = -1;
        for (int i = 1; i + k +1 <= N; i++) 
            if (num1[i]==n){
                if (num2[i + k + 1] == n) {
                    long long temp = f1[i] + f2[i + k + 1];
                    if (ans == -1) {
                        ans = temp;
                    }
                    else
                        ans = min(ans, temp);
                }
            }
        cout << ans << endl;
        return 0;
    }


  • 相关阅读:
    【spring】基于AspectJ的AOP
    【matlab】stanford线性回归,logistic regression 实验
    【Python】列表、字典和元组的排序
    PHP 二叉树的深度优先与广度优先遍历
    PHP 定义栈结构,实现min函数,获取栈最小元素,要求时间复杂度为O(1)
    PHP 短连接生成
    一条SQL查询访问记录表(visit_log)中某个类目(catalog_id)的访问量(visit)排前两名的记录行
    利用 p, 1p 随机数发生器知道等概率发生器
    PHP 将二叉查找树转换为双向链表,要求不能创建新节点,只能调节节点指针
    PHP 求最大递增子序列长度
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626037.html
Copyright © 2011-2022 走看看