CodeForce---Educational Codeforces Round 3 D. Gadgets for dollars and pounds 正题

对于这题笔者无解,只有手抄一份正解过来了:

基本思想就是 :

  • 二分答案,对于第x天,计算它最少的花费f(x),<=s就是可行的,这是一个单调的函数,所以可以二分。
  • 对于f(x)的计算,我用了nlog(n)的算法,遍历m个商品,用c[i]乘以前x天里,第t[i]种货币的最便宜的价格,存放到一个数组里,之后排序,计算前k个的和就是f(x)
  • 前x天里,第t[i]种货币的最便宜的价格是通过预处理得到的,很容易的计算一下前缀最小值就行了。

贴代码吧:

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm> 
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
#define fi first
#define se second
#define mp make_pair
const int maxn = 200005;
int a[maxn],b[maxn],t[maxn],c[maxn];
int n,m,k,s;
int am[maxn],bm[maxn];
int ida[maxn],idb[maxn];
const int inf = 0x3f3f3f3f;

pii pli[maxn];
int id[maxn];

ll f(int x){
    ll ret = 0;
    for (int i=1;i<=m;i++){
        if (t[i] == 1){
            pli[i].fi = (ll)c[i] * (ll)am[x];

        }
        else{
            pli[i].fi = (ll)c[i] * (ll)bm[x];
        }
        pli[i].se = i;
    }
    sort(pli+1,pli+m+1);
    for (int i=1;i<=k;i++){
        ret += pli[i].fi;
    } 

    return ret;
}


int main(){
    cin>>n>>m>>k>>s;
    am[0] = bm[0] = inf;
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if (a[i] < am[i-1]){
            am[i] = a[i];
            ida[i] = i;
        }
        else{
            am[i] = am[i-1];
            ida[i] = ida[i-1];
        }
    }
    for (int i=1;i<=n;i++){
        scanf("%d",&b[i]);
        if (b[i] < bm[i-1]){
            bm[i] = b[i];
            idb[i] = i;
        }
        else{
            bm[i] = bm[i-1];
            idb[i] = idb[i-1];
        }
    }
    for (int i=1;i<=m;i++){
        scanf("%d%d",&t[i],&c[i]);
    }

    ll low,high,mid;
    low = 1,high = n;
    ll d = -1;
    while(low <= high){
        mid = (low + high) / (ll)2;
        if (f(mid) <= s){
            high = mid - 1;
            d = mid;
            for (int i=1;i<=k;i++){
                id[i] = pli[i].se;
            }
        }
        else{
            low = mid + 1;
        }
    }
    cout << d <<"\n";
    if (d == (ll)-1)
        return 0;
    int x = (int)d;
    for (int i=1;i<=k;i++){
        printf("%d %d\n",id[i],t[id[i]]==1?ida[x]:idb[x]);
    }

    return 0;
}

 

posted @ 2015-12-21 21:48  流年易逝  阅读(184)  评论(0编辑  收藏  举报