您的位置:首页 > 其它

Codeforces Educational Codeforces Round 3 D. Gadgets for dollars and pounds(二分 + 贪心)

2015-12-20 01:52 399 查看
题意:

给定N≤2×105天的dollar和pound的兑换率,总共有M≤105个玩具售卖,分为1和2两种

要买k≤M个,现有s≤109钱,问最快哪天可以买到,一天可以买多个

分析:

一天可以买多个,那显然一次性买好最好

今天可以买到,明天也能买到,显然的单调性,维护一个前缀兑换率的min,记录下取到最小值的那一天,二分天数

两种玩具分开维护个前缀和,只有两种,枚举其中一种的个数,另一个可以算出来,判断是否可以买到

问题解决,不算排序,复杂度O(klogn)

代码:

//
//  Created by TaoSama on 2015-12-20
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

typedef long long LL;
typedef pair<LL, int> P;

int n, m, k, s;
P a
, b
;
P one
, two
;
int cnt1, cnt2, ans, ans1, ans2;

bool check(int x) {
LL dollar = a[x].first, pound = b[x].first;
for(int i = 0; i <= k && i <= cnt1; ++i) {
if(k - i > cnt2) continue;
LL sum = one[i].first * dollar + two[k - i].first * pound;
if(sum <= s) {
ans = i;
ans1 = a[x].second;
ans2 = b[x].second;
return true;
}
}
return false;
}

int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

while(scanf("%d%d%d%d", &n, &m, &k, &s) == 4) {
a[0].first = b[0].first = INF;
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &a[i].first);
a[i].second = a[i - 1].second;
if(a[i].first < a[i - 1].first)
a[i].second = i;
else a[i].first = a[i - 1].first;
}
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &b[i].first);
b[i].second = b[i - 1].second;
if(b[i].first < b[i - 1].first)
b[i].second = i;
else b[i].first = b[i - 1].first;
}

cnt1 = cnt2 = 0;
for(int i = 1; i <= m; ++i) {
int x, y; scanf("%d%d", &x, &y);
if(x == 1) one[++cnt1] = P(y, i);
else two[++cnt2] = P(y, i);
}
sort(one + 1, one + 1 + cnt1);
sort(two + 1, two + 1 + cnt2);
for(int i = 1; i <= cnt1; ++i)
one[i].first += one[i - 1].first;
for(int i = 1; i <= cnt2; ++i)
two[i].first += two[i - 1].first;

int l = 1, r = n;
while(l <= r) {
int m = l + r >> 1;
if(check(m)) r = m - 1;
else l = m + 1;
}

if(l == n + 1) puts("-1");
else {
printf("%d\n", l);
for(int i = 1; i <= ans; ++i)
printf("%d %d\n", one[i].second, ans1);
for(int i = 1; i <= k - ans; ++i)
printf("%d %d\n", two[i].second, ans2);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分 贪心