Arkady plays Gardenscapes a lot. Arkady wants to build two new fountains. There are n available fountains, for each fountain its beauty and cost are known. There are two types of money in the game: coins and diamonds, so each fountain cost can be either in coins or diamonds. No money changes between the types are allowed.
Help Arkady to find two fountains with maximum total beauty so that he can buy both at the same time.
题意
有 n 个待建的喷泉,每个的建造代价为 pi coins 或者 pi diamonds (coins 和 diamonds 不可互相兑换),每个喷泉的魅力为 bi 。问在原有 c coins 和 d diamonds 的情况下,选择两个喷泉,使得在能支付代价的前提下,魅力值最高?
解题思路
有四种情况:
- 建两个代价单位为 coins 的喷泉
- 建两个代价单位为 diamonds 的喷泉
- 一个代价单位为 coins 的喷泉和一个代价单位为 diamonds 的喷泉
- 无法建造
以情况 1 为例:对于第 i 个代价单位为 coins 的喷泉,选择前 i-1 个喷泉中满足代价 <= c-p[i]
且魅力最大的喷泉。
如此,该问题即可转化为求区间最值问题(在代价 [1, c-p[i]] 内的最大魅力)。用树状数组、线段树等都可解决。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 100000 + 1;
int n, c, d, b, p;
char s;
const int TREE_SIZE = (N << 2) + 10;
class IntervalTree
{
private:
int Cover[TREE_SIZE],Top[TREE_SIZE];
int size;
int _Query(int a,int b,int l,int r,int idx)
{
if(a <= l && b >= r) return Top[idx];
int mid = (l+r)>>1, ret = Cover[idx];
if(a<=mid) ret = max(ret,_Query(a,b,l,mid,idx<<1));
if(b>mid) ret = max(ret,_Query(a,b,mid+1,r,(idx<<1)+1));
return ret;
}
void _Modify(int a,int l,int r,int idx,int d)
{
if(l==r && l==a)
{
Cover[idx]=Top[idx]=d;
return;
}
int mid = (l+r)>>1;
if(a<=mid) _Modify(a,l,mid,idx<<1,d);
else _Modify(a,mid+1,r,(idx<<1)+1,d);
Top[idx]=max(Top[idx<<1],Top[(idx<<1)+1]);
}
public:
IntervalTree(){
memset(Cover,0,sizeof(Cover));
memset(Top,0,sizeof(Top));
size = (TREE_SIZE>>2) - 1;
}
IntervalTree(int size):size(size){
memset(Cover,0,sizeof(Cover));
memset(Top,0,sizeof(Top));
}
int Query(int a,int b){
return _Query(a,b,1,size,1);
}
void Modify(int a,int d){
return _Modify(a,1,size,1,d);
}
}C, D;
int main()
{
scanf("%d %d %d",&n,&c,&d);
int ans = 0;
for(int i=1;i<=n;i++)
{
scanf("%d %d %c",&b,&p,&s);
if(s == 'C') {
if(p>c) continue;
else if(p < c) {
int get = C.Query(1, c-p);
if(get) ans = max(ans, get+b);
}
C.Modify(p, max(C.Query(1, p), b));
} else {
if(p>d) continue;
else if(p < d) {
int get = D.Query(1, d-p);
if(get) ans = max(ans, get+b);
}
D.Modify(p, max(D.Query(1, p), b));
}
}
int g1 = C.Query(1, c);
int g2 = D.Query(1, d);
if(g1 && g2) ans = max(ans, g1+g2);
printf("%d\n", ans);
}