题目
Problem Description
SDUT一个普通的不能再普通的学生R,一天心血来潮想要炒股,于是他掐指算了算X公司和Y公司接下来N天的股票走向。X公司和Y公司很奇怪,他们的股票是捆绑销售的,即必须同时购买或者出售两公司的股票。更奇怪得是每天R最多只能买一股A和一股B的股票(但是R每天都可以卖无限股)。小R算股票走向损失了大量的功力,现在请你帮助R计算在接下来N天R最多可以赚多少钱。
Input
单组输入。
第一行输入一个N(1 <= N <= 100000),代表R算了接下来N天的股票走向。
接着N行每行输入两个以空格隔开得整数Xi(1 <= Xi, Yi <= 200),Yi,代表第i天X公司得股票价格和Y公司的股票价格。
Output
输出一个整数,代表R最多可以赚多少钱。
Sample Input
5 1 1 1 1 5 5 3 4 4 4
Sample Output
17
思路
以前做过一个类似的题,不过最多只能持有一个股票,一开始因为这个错了一次= =
不过这题也不难,根据题意,不难发现,其实两家公司可以看做是一家(反正只能同时买卖),然后只要在股票涨到剩余的最大值之前一直买进,到最大的时候再卖出就可以获利最大了。可以用优先队列实现,不过只用记录当前剩余的天里的最大值,也可以选择用数组模拟优先队列实现。
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN = 1e5+10;
int main()
{
int n;
int x,y;
int a[MAXN]; //用数组模拟优先队列
int sum[MAXN]; //将两家公司看做一家
int flag[500]; //标记当前值出现的次数
int ans;
int cnt; //当前持有的股票数量
int cost; //当前购买股票的花费
int now; //剩余天数中股票的最大值下标
memset(flag,0,sizeof(flag));
scanf("%d",&n);
for(int i=0; i<n; i++) {
scanf("%d%d",&x,&y);
sum[i] = x+y;
a[i] = sum[i];
}
sort(a,a+n);
now = n-1; //将剩余最大值下标指向排序后的最后一个
ans = cost = cnt = 0;
for(int i=0; i<n; i++) {
if(sum[i] == a[now]) { //如果第i天的值为剩余的最大值
ans += (sum[i]*cnt)-cost; //获利
cost = 0; //卖出后清零
cnt = 0;
now--;
while(flag[a[now]]) { //判断改变后所指向的剩余最大值是否已经在前面出现过
flag[a[now]]--;
now--;
}
}
else {
flag[sum[i]]++;
cost += sum[i];
cnt++;
}
}
printf("%d\n",ans);
return 0;
}