E. Life Transfer(双指针)

题目链接:https://codeforces.com/gym/102392/problem/E
题意:给定n个人年龄,年龄达到lc才能骑车,骑车可以载k-1人,骑车代价为pc;年龄达到lm才能骑motor,motor不能载人;可以用魔法,将一个人年龄转移到另一个人,转移一岁的代价为t,但不能转移超过d岁,及a岁的人,其年龄变化范围为 [ a d + 1 , a + d 1 ] [a-d+1,a+d-1] .
题解:枚举骑摩托数,将年龄排序,双指针来弄。代码实现具体细节比较多。
代码copy自vj

//coded by ZJUT_7
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
#define inf 0x3f3f3f3f3f3f3f3f
#define ll long long
ll a[maxn];


int main(){
    ll n,k,lc,lm,pc,pm,t,d;
    scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&n,&k,&lc,&pc,&lm,&pm);
    scanf("%I64d%I64d",&t,&d);
    for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
    sort(a+1,a+n+1);
    ll need=0,have=0,cost=0;
    ll ans=inf;
    int illegal=0;
    for(int i=1;i<=n;i++){
        have+=max(0LL,min(d,a[i]-lm));
        need+=max(0LL,min(d,lm-a[i]));
        if(a[i]+d<lm) illegal++;
    }
    cost=pm*n+need*t;
    if(illegal==0&&have>=need) ans=cost;
    int s=1,e=n;
    ll cnt=0;
    while(e-s+1>=k){
        cnt++;
        for(int i=0;i<k-1;i++){
            need-=max(0LL,min(d,lm-a[i+s]));
            have+=min(d,min(lm,a[i+s])-1);
            if(a[i+s]+d<lm) illegal--;
        }
        need+=max(0LL,lc-max(lm,a[e]));
        have-=max(0LL,min(d,a[e]-lm));
        have+=max(0LL,min(d,a[e]-lc));

        if(a[e]+d<lc) break;
        cost=pm*(n-cnt*k)+cnt*pc+need*t;
        if(illegal==0&&have>=need) ans=min(ans,cost);
        s+=k-1;
        e--;
    }
    if(a[e]+d>=lc){
        cnt++;
        for(int i=0;i<e-s;i++){
            need-=max(0LL,min(d,lm-a[i+s]));
            have+=min(d,min(lm,a[i+s])-1);
            if(a[i+s]+d<lm) illegal--;
        }
        need+=max(0LL,lc-max(lm,a[e]));
        have-=max(0LL,min(d,a[e]-lm));
        have+=max(0LL,min(d,a[e]-lc));
        cost=cnt*pc+need*t;
        if(illegal==0&&have>=need) ans=min(ans,cost);
    }
    if(ans!=inf)
        printf("%I64d\n",ans);
    else
        puts("-1");
}

发布了71 篇原创文章 · 获赞 1 · 访问量 2818

猜你喜欢

转载自blog.csdn.net/weixin_43918473/article/details/103102089
今日推荐