水~ 山理第十一届ACM校赛 G我不是股神 模拟 优先队列

博客围绕SDUT学生R炒股问题展开。R算出X、Y两公司接下来N天股票走向,两公司股票捆绑销售,每天最多买一股,可卖无限股。需计算N天最多获利。思路是将两公司看作一家,在股票涨到剩余最大值前买进,最大时卖出,可用优先队列或数组模拟实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值