2014-03-08 10:54:33Morris
[其他題目][求助][未解] 折價購買最大量
Description
現在有 N 個產品,帶 M 元去購物。
每個產品有兩個價錢,分別為原價和打折後的價錢。
現在有 K 次打折機會,求在 M 元內最多能買多少產品回去。
Input Format
輸入的第一行有一個正整數 T,代表測試資料的組數。
每組測資的第一行有三個整數 N, K, M (1 <= K <= N <= 100,000, M <= 10^15)。
接下來有 N 行,每行有兩個整數 C[i], D[i] (1 <= D[i] <= C[i] <= 10^9),表示該產品的原價和打折後的價錢。
Output Format
對於每組測資輸出一行整數,購買產品的最大數量。
Sample Input
23 0 61 12 23 34 1 73 22 28 14 3
Sample Output
33
解法 by inker.
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
#define MAX_N 100005
struct zkwST {
int M;
pair<long long, int> st[262144 + 10];
pair<long long, int> elem[131072 + 10];
zkwST() {
}
void build(int n) {
for(M = 1; M < n+1; M <<= 1);
for(int i = 2*M-1; i > 0; i--) {
if(i >= M) {
if(i - M > n)
st[i] = make_pair(0, 0);
else
st[i] = elem[i - M];
} else {
st[i].first = st[i<<1].first + st[i<<1|1].first;
st[i].second = st[i<<1].second + st[i<<1|1].second;
}
}
}
pair<long long, int> prefixQuery(long long S) {
pair<long long, int> ret = make_pair(0LL, 0);
int s;
for(s = 1; s < M; ) {
if(st[s<<1].first <= S) {
ret.first += st[s<<1].first;
ret.second += st[s<<1].second;
S -= st[s<<1].first;
s = s<<1|1;
} else {
s = s<<1;
}
}
if(st[s].first <= S) {
ret.first += st[s].first;
ret.second += st[s].second;
}
return ret;
}
void singleUpdate(int index, pair<long long, int> val) {
st[index + M] = elem[index] = val;
for(int s = (index + M)>>1; s > 0; s >>= 1) {
st[s].first = st[s<<1].first + st[s<<1|1].first;
st[s].second = st[s<<1].second + st[s<<1|1].second;
}
}
};
int C[MAX_N], D[MAX_N];
int A[MAX_N], B[MAX_N], mapB[MAX_N];
int N, K;
long long M;
zkwST segTree;
bool cmpD(int i, int j) {
return D[i] < D[j];
}
bool cmpC(int i, int j) {
return C[i] < C[j];
}
struct cmpPQ {
bool operator()(pair<int, int> &a, pair<int, int> &b) const {
return a.first > b.first;
}
};
int main() {
int testcase;
scanf("%d", &testcase);
while(testcase--) {
scanf("%d %d", &N, &K);
scanf("%lld", &M);
for(int i = 0; i < N; i++) {
scanf("%d %d", &C[i], &D[i]);
A[i] = B[i] = i;
} // Di <= Ci
sort(A, A + N, cmpD);
sort(B, B + N, cmpC);
// build no-sale price with prefix-interval-query struct.
for(int i = 1; i <= N; i++) {
mapB[B[i-1]] = i;
segTree.elem[i] = make_pair((long long)C[B[i-1]], 1);
}
segTree.build(N);
// sweeping by sale price (small to large)
priority_queue< pair<int, int>, vector< pair<int, int> > , cmpPQ > pQ;
// pQ maintain size() <= K
int ret = segTree.prefixQuery(M).second;
long long pQcost = 0;
for(int i = 0; i < N; i++) {
pQcost += D[A[i]]; // add sale price
pQ.push(make_pair(C[A[i]] - D[A[i]], A[i])); // <different price, index>
if(pQ.size() > K) {
pair<int, int> p = pQ.top();
pQ.pop();
pQcost += p.first;
}
segTree.singleUpdate(mapB[A[i]], make_pair(0, 0));
if(pQcost > M)
break;
ret = max(ret, segTree.prefixQuery(M - pQcost).second + i+1);
}
printf("%d\n", ret);
}
return 0;
}
/*
100
10 9 819
54 49
95 43
89 40
89 84
64 60
69 58
99 88
78 34
83 62
93 77
10 1 267
52 25
51 17
88 58
86 82
61 55
38 33
36 2
97 44
100 100
85 1
4 2 15
20 3
40 4
50 7
8 8
4 1 11
20 3
40 4
50 7
8 8
4 2 15
20 3
40 4
50 7
8 8
*/