交易所(Exchange, ACM/ICPC NEERC 2006, UVa1598)rust解法

你的任务是为交易所设计一个订单处理系统。要求支持以下3种指令。

BUY p q:有人想买,数量为p,价格为q。

SELL p q:有人想卖,数量为p,价格为q。

CANCEL i:取消第i条指令对应的订单(输入保证该指令是BUY或者SELL)。

交易规则如下:对于当前买订单,若当前最低卖价低于当前出价,则发生交易;对于当前卖订单,若当前最高买价高于当前价格,则发生交易。发生交易时,按供需物品个数的最小值交易。交易后,需修改订单的供需物品个数。当出价或价格相同时,按订单产生的先后顺序发生交易。

样例:

输入

11
BUY 100 35
CANCEL 1
BUY 100 34
SELL 150 36
SELL 300 37
SELL 100 36
BUY 100 38
CANCEL 4
CANCEL 7
BUY 200 32
SELL 500 30

输出

QUOTE 100 35 - 0 99999
QUOTE 0 0 - 0 99999
QUOTE 100 34 - 0 99999
QUOTE 100 34 - 150 36
QUOTE 100 34 - 150 36
QUOTE 100 34 - 250 36
TRADE 100 36
QUOTE 100 34 - 150 36
QUOTE 100 34 - 100 36
QUOTE 100 34 - 100 36
QUOTE 100 34 - 100 36
TRADE 100 34
TRADE 200 32
QUOTE 0 0 - 200 30

分析:

一个订单成交过的部分不能取消。只能取消剩余的部分。比如SELL 150 36,已经成交了100个,还剩余50个,所以当取消这个订单时,只能取消那50个。

解法:

rust 复制代码
use std::{
    collections::{BTreeMap, BTreeSet, HashMap},
    io::{self, Read},
};
struct Order {
    amount: usize,
    price: usize,
    op: String,
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let n: usize = buf.trim().parse().unwrap();

    let mut orders: Vec<Order> = vec![]; //所有订单
    let mut buy_list: BTreeMap<usize, BTreeSet<usize>> = BTreeMap::new(); // 买价对应的订单id
    let mut sell_list: BTreeMap<usize, BTreeSet<usize>> = BTreeMap::new(); //卖价对应的订单id
    let mut buy_amount_price = HashMap::new(); //买价对应的总数量
    let mut sell_amount_price = HashMap::new(); //卖价对应的总数量

    let mut buf = String::new();
    io::stdin().read_to_string(&mut buf).unwrap();
    let mut lines = buf.lines();
    for i in 0..n {
        let mut it = lines.next().unwrap().split_whitespace();
        let cmd = it.next().unwrap();
        let v: Vec<usize> = it.map(|x| x.parse().unwrap()).collect();
        if cmd == "CANCEL" {
            orders.push(Order {
                amount: 0,
                price: 0,
                op: cmd.to_string(),
            });
            let cancel_id = v[0] - 1;
            let aorder = &mut orders[cancel_id];
            if aorder.op == "BUY" {
                sell_amount_price
                    .entry(aorder.price)
                    .and_modify(|x| *x -= aorder.amount);
                aorder.amount = 0;
                if let Some(v) = buy_list.get_mut(&aorder.price) {
                    v.remove(&cancel_id);
                    if v.is_empty() {
                        buy_list.remove(&aorder.price);
                    }
                }
            } else if aorder.op == "SELL" {
                sell_amount_price
                    .entry(aorder.price)
                    .and_modify(|x| *x -= aorder.amount);
                aorder.amount = 0;
                if let Some(v) = sell_list.get_mut(&aorder.price) {
                    v.remove(&cancel_id);
                    if v.is_empty() {
                        sell_list.remove(&aorder.price);
                    }
                }
            }
        } else if cmd == "BUY" || cmd == "SELL" {
            let id = i;
            let amount = v[0];
            let price = v[1];
            let op = cmd.to_string();
            if cmd == "BUY" {
                buy_list
                    .entry(price)
                    .and_modify(|x| {
                        x.insert(id);
                    })
                    .or_insert(BTreeSet::from([id]));
                buy_amount_price
                    .entry(price)
                    .and_modify(|x| *x += amount)
                    .or_insert(amount);
            } else {
                sell_list
                    .entry(price)
                    .and_modify(|x| {
                        x.insert(id);
                    })
                    .or_insert(BTreeSet::from([id]));
                sell_amount_price
                    .entry(price)
                    .and_modify(|x| *x += amount)
                    .or_insert(amount);
            }
            let a = Order { amount, price, op };
            orders.push(a);
        }

        trade(
            &cmd.to_string(),
            &mut buy_list,
            &mut sell_list,
            &mut buy_amount_price,
            &mut sell_amount_price,
            &mut orders,
        );
        if let Some(x) = buy_list.last_entry() {
            let price = x.key();
            print!("QUOTE {} {}", buy_amount_price.get(&price).unwrap(), price);
        } else {
            print!("QUOTE 0 0");
        }
        if let Some(x) = sell_list.first_entry() {
            let price = x.key();
            print!(" - {} {}", sell_amount_price.get(&price).unwrap(), price);
        } else {
            print!(" - 0 99999");
        }
        println!();
    }
}

fn trade(
    op: &String,
    buy_list: &mut BTreeMap<usize, BTreeSet<usize>>,
    sell_list: &mut BTreeMap<usize, BTreeSet<usize>>,
    buy_amount_price: &mut HashMap<usize, usize>,
    sell_amount_price: &mut HashMap<usize, usize>,
    orders: &mut Vec<Order>,
) {
    loop {
        if buy_list.is_empty() || sell_list.is_empty() {
            break;
        }
        let mut buy_entry = buy_list.last_entry().unwrap(); //因为map是升序,而我们要取最大买价,所以每次取最后一个元素
        let mut sell_entry = sell_list.first_entry().unwrap(); //因为map是升序,取最小卖价,每次取第一个元素
        let buy_price = *buy_entry.key();
        let sell_price = *sell_entry.key();
        if buy_price < sell_price {
            break;
        }
        let buy_ids = buy_entry.get_mut();
        let buyid = buy_ids.pop_first().unwrap();
        let sell_ids = sell_entry.get_mut();
        let sellid = sell_ids.pop_first().unwrap();

        let min_amount = orders[buyid].amount.min(orders[sellid].amount);

        buy_amount_price
            .entry(buy_price)
            .and_modify(|x| *x -= min_amount);
        sell_amount_price
            .entry(sell_price)
            .and_modify(|x| *x -= min_amount);

        orders[buyid].amount -= min_amount;
        orders[sellid].amount -= min_amount;
        if orders[buyid].amount > 0 {
            buy_ids.insert(buyid);
        } else if buy_ids.is_empty() {
            buy_list.remove(&buy_price);
        }
        if orders[sellid].amount > 0 {
            sell_ids.insert(sellid);
        } else if sell_ids.is_empty() {
            sell_list.remove(&sell_price);
        }
        if op == "BUY" {
            println!("TRADE {} {}", min_amount, sell_price);
        } else if op == "SELL" {
            println!("TRADE {} {}", min_amount, buy_price);
        }
    }
}
相关推荐
资源补给站1 小时前
大恒相机开发(2)—Python软触发调用采集图像
开发语言·python·数码相机
m0_748247551 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
刘大辉在路上1 小时前
突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除
git·后端·gitlab·版本管理·源代码管理
6.941 小时前
Scala学习记录 递归调用 练习
开发语言·学习·scala
FF在路上2 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
众拾达人2 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.2 小时前
Mybatis-Plus
java·开发语言
不良人天码星2 小时前
lombok插件不生效
java·开发语言·intellij-idea
源码哥_博纳软云3 小时前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
学会沉淀。3 小时前
Docker学习
java·开发语言·学习