交易所(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);
        }
    }
}
相关推荐
齐 飞6 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
童先生19 分钟前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
lulu_gh_yu20 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
LunarCod23 分钟前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
Re.不晚44 分钟前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
老秦包你会1 小时前
Qt第三课 ----------容器类控件
开发语言·qt
凤枭香1 小时前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
ULTRA??1 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
远望清一色1 小时前
基于MATLAB的实现垃圾分类Matlab源码
开发语言·matlab