交易所(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);
        }
    }
}
相关推荐
Bruce_Liuxiaowei2 分钟前
Python 实例赋值遮蔽类属性:一个从不报错的静默陷阱
开发语言·python·语法糖
IT_陈寒7 分钟前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端
光影少年18 分钟前
Express 中间件原理
后端·node.js·express
梦醒沉醉28 分钟前
std1.97.1——cmp模块细览
rust
aramae1 小时前
MySQL内置函数(7)
开发语言·笔记·后端·mysql·其他
徐小夕2 小时前
存量.doc 文档怎么办?JitWord 开源转换库打通旧文档到在线协同全链路
后端·架构·github
ee又momo2 小时前
一次 JWT Token 过期续期的踩坑记录
后端
二月龙2 小时前
App 瘦身实战:图片、so 库、资源压缩,安装包体积减小 40%
后端
大勇前进2 小时前
Kotlin 协程实战避坑:90% 的人都会踩的生命周期泄漏问题
后端
苏三说技术3 小时前
Spring AI、LangChain4j、AgentScope、Embabel,哪个AI框架更好?
后端