tyvj 2017.9.17 test P4867 天天寄快递(暴力)

额 第二天的模拟赛吃鸡去了所以没参加

历时两天把这道day2 t1做了

感谢xd大佬博客的启发

天天寄快递
express.in/.out/.cpp
【问题描述】
天天暑假时帮别⼈寄送快递,经历了⼀个暑假,天天积累了不少数据, 想对快递公司进⾏⼀下评分,得到快递公司的质量⽔平。 总共有 n 家快递公司,编号为 1..n。现在天天有 m 天的寄送快递数据, 其中第 i 天使⽤第 ei 家快递公司,快递在路上花了 ti 天时间。⼀开始每个 快递公司的评分都为 0,对于⼀家快递公司,如果⼀个包裹花了 ti 天寄到, 那么对这家快递公司的评分贡献为 2−ti,(如果花的时间超过两天得分就会 变成负的啦)。 然⽽事情没有这么简单,如果某⼀天的数据丢掉了,天天为了公平起见 就忽略掉这天的数据。于是快递公司联盟决定雇佣⼀个⼩偷,⼩偷可以偷⾛ 最多 s 天的数据,使得每个公司的信⽤得分⾄少增加 k,且所有快递公司的 信⽤总和尽量⼤。 若如果被偷以后,⽆法让每个公司的信⽤得分都⾄少增加 k,输出 −23333333,否则请你输出被偷后, 所有快递公司的信⽤得分的和最多增 加多少。
【输入格式】 第⼀⾏四个整数 n,m,s,k,其中 1 ≤ n,m ≤ 100,000,0 ≤ s ≤ m,0 ≤ k ≤ 109。 接下来 m ⾏,每⾏两个整数。接下来的第 i ⾏为 ei,ti,其中 1 ≤ ei ≤ n,0 ≤ ti ≤ 109。
【输出格式】
⼀个整数,为题⽬要求的答案。
2
【样例输入】
2 5 4 22 1 1 1 40 2 25 2 30 2 0
【样例输出】
89
【样例解释】
⼩偷可以偷 4 天的数据,但是⼩偷实际上只偷了第 2,3,4 天的数据,1 号公司获得了 38 分的提升,2 号公司获得了 23 + 28 分的提升,都满⾜了 最⼩提升 22 分的要求。
【数据规模和约定】 对于 30% 的数据,1 ≤ n,m ≤ 20。 对于 100% 的数据,1 ≤ n,m ≤ 200,000,。

这道题就是暴力,排序之后去掉负值然后算就行了

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<vector>
#define ll long long
#define f(i,l,r) for(int i = l;i <= r;i++)
using namespace std;
const int maxn = 200005;
inline void read(int &x){                        //快读
    int f = 1;x = 0;char ch;
    do{ch = getchar();if(ch == '-') f = -1;}
    while(ch < '0' || ch > '9'); do{
        x = x * 10 + ch - '0';
        ch =getchar();
    }
    while(ch >= '0' && ch <= '9'); x*=f;
} 
struct xd{
    int e,t;
}a[maxn];
int n,m,s,k,f = 0,now[maxn];
bool flag[maxn];
int cmp(xd a,xd b){                     //排序
    return a.t < b.t;
}
int main(){
    read(n);read(m);read(s);read(k);
    f(i,1,m){                //读入
        read(a[i].e);read(a[i].t);
        a[i].t = 2 - a[i].t;
    }
    sort(a+1,a+m+1,cmp);
    f(i,1,m){
        if(a[i].t > 0) break;      //当有大于0的时候跳出
        if(now[a[i].e] < k){      //处理
        now[a[i].e] -= a[i].t;
        flag[i] = 1;           //标记当前的已经不需要加
        f++;                //天数加一
        }
    } 
    if(f > s){               //所用天大于需要天就不行
        printf("-23333333\n");
        return 0;
    }
    f(i,1,n){                //有小于所需的值就不行
        if(now[i] < k){
        printf("-23333333\n");
        return 0;
        }
    }
    if(f != s) f(i,1,m){         //没什么好说的就是处理没处理过的数据
        if(flag[i] == 1) continue;
        if(a[i].t > 0 || f == s) break;  //达成条件跳出循环
        now[a[i].e] -= a[i].t;
        f++;
    }
    long long ans = 0;                  //不开long long只有30分
    f(i,1,n){
        ans += now[i];
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2017-09-20 17:38  59s  阅读(191)  评论(0编辑  收藏  举报