题目内容
问题描述
试题编号: 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(){
}
item(double pi,long long ni,int fi):price(pi),number(ni),flag(fi){
}
};
struct cmp
{
bool operator()(item x,item y)
{
if(x.price==y.price) return x.flag>y.flag; //buy在sell上面
else return x.price<y.price;
}
};
priority_queue<item,vector<item>,cmp> Q;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
string str;
long long buynum=0,sellnum=0;
int nowi=0;
while(getline(cin,str))
{
allstr[nowi++]=str;
if(str[0]=='c')
{
int ci=stoi(str.substr(7));
allstr[ci-1]="";
}
}
for(int i = 0 ; i < nowi ; i++)
{
if(allstr[i]=="") continue;
istringstream ss(allstr[i]);
string content;
double pi;
long long ni;
if(allstr[i][0]=='b')
{
ss>>content;
ss>>pi>>ni;
Q.push(item(pi,ni,0));
}
else if(allstr[i][0]=='s')
{
ss>>content;
ss>>pi>>ni;
Q.push(item(pi,ni,1));
sellnum+=ni;
}
}
while(!Q.empty())
{
item now=Q.top();
Q.pop();
if(now.flag==0)
{
buynum+=now.number;
if(ansnum<min(buynum,sellnum))
{
ansnum=min(buynum,sellnum);
ansprice=now.price;
}
}
else sellnum-=now.number;
}
cout<<fixed<<setprecision(2)<<ansprice<<" "<<ansnum<<"\n";
return 0;
}