【ccf2014-12-03】集合竞价

本文介绍了如何根据客户订单确定股票开盘价和开盘成交量的问题,涉及处理buy、sell和cancel订单,目标是最大化开盘成交量。解题思路是使用优先队列,按照价格由高到低排序,遍历过程中更新buy和sell的数量,最终找到最大成交量对应的开盘价。
摘要由CSDN通过智能技术生成

题目内容

问题描述
试题编号: 201412-3
试题名称: 集合竞价
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  某股票交易所请你编写一个程序,根据开盘前客户提交的订单来确定某特定股票的开盘价和开盘成交量。
  该程序的输入由很多行构成,每一行为一条记录,记录可能有以下几种:
  1. buy p s 表示一个购买股票的买单,每手出价为p,购买股数为s。
  2. sell p s 表示一个出售股票的卖单,每手出价为p,出售股数为s。
  3. cancel i表示撤销第i行的记录。
  如果开盘价为p0,则系统可以将所有出价至少为p0的买单和所有出价至多为p0的卖单进行匹配。因此,此时的开盘成交量为出价至少为p0的买单的总股数和所有出价至多为p0的卖单的总股数之间的较小值。
  你的程序需要确定一个开盘价,使得开盘成交量尽可能地大。如果有多个符合条件的开盘价,你的程序应当输出最高的那一个。
输入格式
  输入数据有任意多行,每一行是一条记录。保证输入合法。股数为不超过108的正整数,出价为精确到恰好小数点后两位的正实数,且不超过10000.00。
输出格式
  你需要输出一行,包含两个数,以一个空格分隔。第一个数是开盘价,第二个是此开盘价下的成交量。开盘价需要精确到小数点后恰好两位。
样例输入
buy 9.25 100
buy 8.88 175
sell 9.00 1000
buy 9.00 400
sell 8.92 400
cancel 1
buy 100.00 50
样例输出
9.00 450
评测用例规模与约定
  对于100%的数据,输入的行数不超过5000。

解题思路

用构造一个item结构,存储价格,股票数,买/卖家。
因为[使得开盘成交量尽可能地大。如果有多个符合条件的开盘价,你的程序应当输出最高的那一个。]
所以需要遍历价格从高到低,并且保存最大的成交量。
但是仔细分析题目[如果开盘价为p0,则系统可以将所有出价至少为p0的买单和所有出价至多为p0的卖单进行匹配。因此,此时的开盘成交量为出价至少为p0的买单的总股数和所有出价至多为p0的卖单的总股数之间的较小值。]。可以得到最终的开盘价格一定是buy的价格,这里就不证明了。
所以这里选用优先队列Q存储结构体,并按照价格由高到低排序,并且把buy排在sell前面。
并且建buynum和sellnum来存储当前可以交易的数量,其中buynum初始化为0,而sellnum初始化为所有sell的和。(因为价格从高到底遍历)
以下为核心代码:
每次访问Q.top(),如果是buy,则buynum加上这个buy的item的股票数,然后更新最大成交量和价格。
如果是sell,则sellnum减去当前sell的item的股票数。(不用更新,因为必定不是最大交易量)

之后就是题目的几个坑:
1.股票数要用longlong存
2.处理输入的时候需要处理cancel行为,第一点是cancel不会cancel本身,即如果cancel本身不会造成影响。第二点是cancel的序列号是在输入排序 中的编号(第一次没有考虑这个,提交代码只有30分,搞了我一个小时才找出来)

以下为ac代码:

#include "bits/stdc++.h"
using namespace std;

string allstr[5005];
long long ansnum;
double ansprice;

struct item
{
   
    double price;
    long long number;
    int flag;   //0-buy,1-sell
    item(){
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值