售票系统 题解

题目描述

某次列车途经 C 个城市,城市编号依次为 \(1\)\(C\),列车上共有 \(S\) 个座位,铁路局规定售出的车票只能是坐票, 即车上所有的旅客都有座。售票系统是由计算机执行的,每一个售票申请包含三个参数,分别用 \(O,D,N\) 表示,\(O\) 为起始站,\(D\) 为目的地站,\(N\) 为车票张数。售票系统对该售票申请作出受理或不受理的决定,只有在从 \(O\)\(D\) 的区段内列车上都有 \(N\) 个或 \(N\) 个以上的空座位时该售票申请才被受理。

请你写一个程序,实现这个自动 售票系统。

输入格式

第一行包含三个用空格隔开的整数 \(C,S\)\(R\),其中 \(1 \le C \le 60000, 1 \le S \le 60000, 1 \le R \le 60000\)。C 为城市个数,S 为列车上的座位数,R 为所有售票申请总数。

接下来的 R 行每行为一个售票申请,用三个由空格隔开的整数 \(O,D\)\(N\) 表示,\(O\) 为起始站,\(D\) 为目的地站,\(N\) 为车票张数,其中 \(1 \le D \le C, 1 \le O \le C\),所有的售票申请按申请的时间从早到晚给出。

输出格式

输出共有 \(R\) 行,每行输出一个 YESNO,表示当前的售票申请被受理或不被受理。

样例

样例输入

4 6 4
1 4 2
1 3 2
2 4 3
1 2 3

样例输出

YES
YES
NO
NO

数据范围与提示

对于 \(30\%\) 的数据,\(1 \le C \le 350, 1 \le S \le 200, 1 \le R \le 500\)

对于 \(100\%\) 的数据,\(1 \le C \le 60000, 1 \le S \le 60000, 1 \le R \le 60000\)

Analysis

  • 题目一眼线段树。
  • 维护区间最小值,只有当所询问的区间的最小值大于等于请求车票张数是才能同意申请,同时需要更新所询问的区间的最小值。
  • 然而本题有一个坑点,就是乘客到了目的地后会下车,所以到车站后车上的人数会减少,故查询和更新的区间应当为左闭右开区间 \([O, D)\)。(警钟撅烂,考试时没考虑到)

Code

#include <bits/stdc++.h>
using namespace std;

const int maxn = 60005;
int n, m, q;
struct SegmentTree {
    int left, right;
    int minv, tag;
} tree[maxn << 2];

inline void pushup(int root) {
    tree[root].minv = min(tree[root << 1].minv, tree[root << 1 | 1].minv);
}

inline void pushdown(int root) {
    if (!tree[root].tag) return;
    tree[root << 1].minv += tree[root].tag;
    tree[root << 1 | 1].minv += tree[root].tag;
    tree[root << 1].tag += tree[root].tag;
    tree[root << 1 | 1].tag += tree[root].tag;
    tree[root].tag = 0;
}

void build(int root, int l, int r) {
    tree[root].left = l;
    tree[root].right = r;
    if (l == r) {
        tree[root].minv = m;
        return;
    }
    int mid = (l + r) >> 1;
    build(root << 1, l, mid);
    build(root << 1 | 1, mid + 1, r);
    pushup(root);
}

void update(int root, int l, int r, int val) {
    if (l > r) return; // 好习惯:防止出现左端点大于右端点的情况
    if (tree[root].left >= l && tree[root].right <= r) {
        tree[root].minv += val;
        tree[root].tag += val;
        return;
    }
    pushdown(root);
    int mid = (tree[root].left + tree[root].right) >> 1;
    if (mid >= l) update(root << 1, l, r, val);
    if (mid < r) update(root << 1 | 1, l, r, val);
    pushup(root);
}

int query(int root, int l, int r) {
    if (l > r) return 0; // 好习惯:防止出现左端点大于右端点的情况
    if (tree[root].left >= l && tree[root].right <= r) {
        return tree[root].minv;
    }
    pushdown(root);
    int mid = (tree[root].left + tree[root].right) >> 1;
    int ans = 0x3f3f3f3f;
    if (mid >= l) ans = min(ans, query(root << 1, l, r));
    if (mid < r) ans = min(ans, query(root << 1 | 1, l, r));
    return ans;
}

int main() {
    // freopen("railway.in", "r", stdin);
    // freopen("railway.out", "w", stdout);
    scanf("%d%d%d", &n, &m, &q);
    build(1, 1, n);
    while (q--) {
        int l, r, val;
        scanf("%d%d%d", &l, &r, &val);
        int rest = query(1, l, r - 1);
        if (rest >= val) {
            printf("YES\n");
            update(1, l, r - 1, -val);
        } else {
            printf("NO\n");
        }
    }
    return 0;
}

本篇在洛谷博客同步发布。

posted @ 2024-08-19 20:57  jxyanglinus  阅读(55)  评论(0)    收藏  举报