交易所(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);
        }
    }
}
相关推荐
superman超哥1 天前
Serde 性能优化的终极武器
开发语言·rust·编程语言·rust serde·serde性能优化·rust开发工具
东东5161 天前
学院个人信息管理系统 (springboot+vue)
vue.js·spring boot·后端·个人开发·毕设
一个响当当的名号1 天前
lectrue9 索引并发控制
java·开发语言·数据库
2401_832131951 天前
模板错误消息优化
开发语言·c++·算法
进阶小白猿1 天前
Java技术八股学习Day30
java·开发语言·学习
lead520lyq1 天前
Golang本地内存缓存
开发语言·缓存·golang
zhaotiannuo_19981 天前
Python之2.7.9-3.9.1-3.14.2共存
开发语言·python
2601_949868361 天前
Flutter for OpenHarmony 电子合同签署App实战 - 主入口实现
开发语言·javascript·flutter
三水不滴1 天前
Redis缓存更新策略
数据库·经验分享·redis·笔记·后端·缓存
helloworldandy1 天前
高性能图像处理库
开发语言·c++·算法