You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
3.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1e6 + 10;
// 线段树模板
struct Node {
int l, r;
int mx; // 区间人数最大值
int tag; // 懒标记
} tr[N << 2];
void pushup(int u) {
tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx); // 向上更新区间最大值
}
void pushdown(int u) {
if (tr[u].tag) { // 如果u节点有懒标记
tr[u << 1].tag += tr[u].tag, tr[u << 1].mx += tr[u].tag; // 将懒标记下传给左儿子,并且,区间整体加上一个数,意味着区间最大值也加上了这个数
tr[u << 1 | 1].tag += tr[u].tag, tr[u << 1 | 1].mx += tr[u].tag; // 同上
tr[u].tag = 0; // 清除u节点懒标记
}
}
void build(int u, int l, int r) {
tr[u] = {l, r};
if (l == r) return; // 这里与前一个题不同不需要初始值1因为表示默认没有人在这个区间坐车
int mid = (l + r) >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
// 此题因为只是构建一个空的线段树,不需要更新父节点信息
// 当然为了和背的模板一样也可以无脑的写上pushup(u);
pushup(u);
}
// 区间[l,r]统一增加v
void modify(int u, int l, int r, int v) {
if (l <= tr[u].l && r >= tr[u].r) {
tr[u].tag += v; // 懒标记 (什么时候懒标记可以叠加,什么时候不可以呢?)
tr[u].mx += v; // 区间人数最大值也需要加上v
return;
}
// 下放懒标记
pushdown(u);
// 分裂
int mid = (tr[u].l + tr[u].r) >> 1;
if (l <= mid) modify(u << 1, l, r, v); // 与左区间有交集
if (r > mid) modify(u << 1 | 1, l, r, v); // 与右区间有交集
pushup(u); // 将结果的变更更新到祖先节点
}
int query(int u, int l, int r) {
if (l > tr[u].r || r < tr[u].l) return 0; // 递归出口不在我管辖范围内的情况返回0
if (l <= tr[u].l && tr[u].r <= r) return tr[u].mx; // 完整区间覆盖,返回区间和
// 下放懒标记
pushdown(u);
// 分裂
int mid = (tr[u].l + tr[u].r) >> 1;
int mx = 0;
if (l <= mid) mx = query(u << 1, l, r); // 与左子区间有交集
if (r > mid) mx = max(mx, query(u << 1 | 1, l, r)); // 与右子区间有交集
return mx;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("HDU3577.in", "r", stdin);
#endif
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
int T;
int k, q;
int a, b;
cin >> T;
int cas = 0;
while (T--) {
cin >> k >> q;
// 构建线段树
build(1, 1, N); // 学会上限的处理技巧
vector<int> res;
for (int i = 1; i <= q; i++) {
cin >> a >> b;
// a上车b下车b位置可以售卖[a,b)
// 总结这玩意开区间的位置不在讨论范围内啊不用处理就OK啊~
// 准备在区间[a,b)售票区间的最大值是k-1,保证在区间内不超过k
if (query(1, a, b - 1) < k) {
// 对于线段树的[a,b)=[a,b-1]整体区间+1
modify(1, a, b - 1, 1);
// 记录第i次操作是成功的操作
res.push_back(i);
}
}
printf("Case %d:\n", ++cas);
// 注意格式输出
for (auto c : res) printf("%d ", c);
printf("\n\n");
}
return 0;
}