主要是线段树+离散化,稍微说几点😶
- 询问规模很大(n<=10^5),没有时间直接遍历区间,题目要求实现查询和修改区间,联想到线段树。
- 同时车站号数值也很大(可能m>>10^5),直接按车站号开数组空间会不够,估计很多同学卡在这了。
- 考虑到真实存在的车站数其实不超过2n,通过离散化(对车站号排序+去重+取秩)将原来离散的车站号转化成可操作的紧凑的车站号。
- “请求订购从a站到b站的k张票”——很多同学(比如我)可能觉得常识上火车从a车站接人上车,到达b车站了该放人下车了吧??然而本题测试数据告诉我们:并没有,即使到了b车站他们也还在车上!
- 此外本题还可以参考tzoj题目id3315:买火车票,不过那道题数据很小,不用做离散化。
- 要求线段树修改区间的,懒标记能用就用,不然更新操作的时间复杂度肯定不止O(logn),可能过不了。
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 100000 using namespace std; int tree[MAX << 3], lazy[MAX << 3];//递归式线段树和懒标记数组 int a[MAX], b[MAX], k[MAX]; int discrete(int* a, int* b, int n) { int temp[MAX << 1], len = 0; for(int i = 0; i < n; i++) { temp[len++] = a[i]; temp[len++] = b[i]; } sort(temp, temp + len); len = unique(temp, temp + len) - temp; for(int i = 0; i < n; i++) { a[i] = lower_bound(temp, temp + len, a[i]) - temp; b[i] = lower_bound(temp, temp + len, b[i]) - temp; } return len; } int getmax(int a, int b) { return a >= b ? a : b; } void build() { memset(tree, 0, sizeof(tree)); memset(lazy, 0, sizeof(lazy)); return; } void pushup(int root) { tree[root] = getmax(tree[root << 1], tree[root << 1 | 1]); return; } void pushdown(int root) { if(lazy[root] == 0) return; tree[root << 1] += lazy[root]; tree[root << 1 | 1] += lazy[root]; lazy[root << 1] += lazy[root]; lazy[root << 1 | 1] += lazy[root]; lazy[root] = 0; return; } void update(int a, int b, int k, int l, int r, int root) { if(a <= l && r <= b) { tree[root] += k; lazy[root] += k; return; } pushdown(root); int mid = (l + r) >> 1; if(a <= mid) update(a, b, k, l, mid, root << 1); if(mid + 1 <= b) update(a, b, k, mid + 1, r, root << 1 | 1); pushup(root); } int query(int a, int b, int l, int r, int root) { int ans = 0; if(a <= l && r <= b) return tree[root]; pushdown(root); int mid = (l + r) >> 1; if(a <= mid) ans = getmax(ans, query(a, b, l, mid, root << 1)); if(mid + 1 <= b) ans = getmax(ans, query(a, b, mid + 1, r, root << 1 | 1)); return ans; } int main() { int n = 0, m = 0, len = 0; while(scanf("%d%d", &n, &m) != EOF) { for(int i = 0; i < n; i++) scanf("%d%d%d", &a[i], &b[i], &k[i]); //建树 build(); //对所有车站做离散化并拿到真实的车站数 len = discrete(a, b, n); for(int i = 0; i < n; i++) { //区间查询+区间修改 if(query(a[i], b[i], 0, len - 1, 1) + k[i] <= m) { update(a[i], b[i], k[i], 0, len - 1, 1); printf("1\n"); } else printf("0\n"); } } return 0; }