CCF 201412-3 集合竞价

问题描述
试题编号: 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。

 

 

本代码暴力枚举[minval,maxval]检索答案

注意:

刚开始以为会存在这样的情况:

 

存在一条删除命令 要删除买进或者卖出的股票
再来一条删除命令 要删除前面的删除命令/相当于前面的删除命令失效了
 
因为题目描述的不清楚,导致了我这样的幻觉~
 

网上有其他博主给出其他优质解决方案,如:证明了开盘价一定是买家的价格之一

#include<stdio.h>
#include<algorithm>
#include<iostream>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int N=5005;
int n,m,c1,c2,num,l=2e9,r=-2e9;bool vis[N];char str[N];
int b1[N],b2[N];ll s1[N],s2[N];ll ans;
pair<int,int> buy[N],sell[N];
struct node{
    int opt,a,b;
    node(int opt=0,int a=0,int b=0):opt(opt),a(a),b(b){}
}da[N];
ll check(int now){
    ll res1(0),res2(0);
    int p1=lower_bound(b1+1,b1+c1+1,now)-b1;
    int p2=upper_bound(b2+1,b2+c2+1,now)-b2;
    res1=s1[c1]-s1[p1-1];//[p1,c1]
//    if(b2[p2]>now) p2--;//[1,p2]
    res2=s2[p2-1];
    // the above is faster than the below
//    for(int i=1;i<=c1;i++) if(buy[i].fi>=now) res1+=buy[i].se;
//    for(int i=1;i<=c2;i++) if(sell[i].fi<=now) res2+=sell[i].se;
    return min(res1,res2);
}
int main(){
    while(gets(str)){
        double a=0;int opt,b;
        if(str[0]=='c') opt=-1,sscanf(str,"%*s%d",&b),vis[b]=1;
        else{
            opt=(str[0]=='b')?1:2;
            sscanf(str,"%*s%lf%d",&a,&b);
        } 
        da[++n]=node(opt,(int)((a+1e-4)*100.0),b);
        //上面这个改成下面就只有90分,woc 这TMD谁知道!阴沟里翻船 
//        da[++n]=node(opt,(int)(a*100.0),b);
    }
//    for(int i=n;i;i--) if(da[i].opt==-1&&!vis[i]) vis[da[i].b]=1;
    for(int i=1;i<=n;i++){
        if(~da[i].opt&&!vis[i]){
            da[++m]=da[i];
        }
    }
    for(int i=1;i<=m;i++){
        l=min(l,da[i].a);r=max(r,da[i].a);
        if(da[i].opt==1) buy[++c1]=mp(da[i].a,da[i].b);else
        if(da[i].opt==2) sell[++c2]=mp(da[i].a,da[i].b);
    }
    
    sort(buy+1,buy+c1+1);
    sort(sell+1,sell+c2+1);
    
    for(int i=1;i<=c1;i++) b1[i]=buy[i].fi,s1[i]=s1[i-1]+buy[i].se;
    for(int i=1;i<=c2;i++) b2[i]=sell[i].fi,s2[i]=s2[i-1]+sell[i].se;
    
    for(int i=l;i<=r;i++){
        ll res=check(i);
        if(ans<=res) ans=res,num=i;
    }
    
    printf("%.2lf %lld\n",(1.0*num)/100.0,ans);
    return 0;
}

 

易错点

#include<iostream>
using namespace std;
int main(){
    double a=8888.8;
    cout<<(int)((a+1e-4)*100.0)<<'\n';//==>888880
    cout<<(int)(a*100.0)<<'\n';//==>888879
    return 0;
}

 

posted @ 2020-03-30 20:01  神犇(shenben)  阅读(203)  评论(0编辑  收藏  举报