题解:AT_joisc2021_c フードコート (Foodcourt)
Camellia2025 · · 题解
整体二分好题。
首先这个离开操作完全不必要,每次查询时只需要加上离开的人数,然后在一共来的人数查询即可,这东西可以用一个树状数组维护一共来过的人数,一个线段树维护当前的人数,离开人数使两者作差即可,在输入询问时就可以处理到操作中。
然后是对所有操作整体二分,二分到某个操作时,如果那该操作加入的人正好刚好满足某一个询问,那么就是那个询问的答案,这里直接统计,因为后面继续分治时如果有更小的满足会自动覆盖掉。
理解代码应该更容易懂。
code
#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define INF 1000000000000000000
using namespace std;
const int N = 3e5;
struct BIT {
int c[N];
inline void add (int x, int k) {
for (; x < N; x += (x & -x)) c[x] += k;
}
inline int sum (int x) {
int res = 0;
for (; x; x -= (x & -x)) res += c[x];
return res;
}
} bit;
struct SegmentTree {
int sum[N << 2], tag[N << 2], matag[N << 2];
#define ls (p << 1)
#define rs (p << 1 | 1)
#define mid ((l + r) >> 1)
inline int max (int a, int b) {
return a > b ? a : b;
}
inline void pushup (int p) {
sum[p] = max (sum[ls], sum[rs]);
}
inline void push (int &x, int p) {
x = max (x + tag[p], matag[p]);
}
inline void pushdown (int p) {
push (sum[ls], p), push (sum[rs], p), push (matag[ls], p), push (matag[rs], p), tag[ls] += tag[p], tag[rs] += tag[p], matag[p] = tag[p] = 0;
}
void update (int p, int l, int r, int L, int R, int k) {
if (L <= l and r <= R) return sum[p] = max (sum[p] + k, 0), tag[p] += k, matag[p] = max (matag[p] + k, 0), void ();
pushdown (p);
if (L <= mid) update (ls, l, mid, L, R, k);
if (R > mid) update (rs, mid + 1, r, L, R, k);
pushup (p);
}
int query (int p, int l, int r, int x) {
if (l == r) return sum[p];
return pushdown (p), (x <= mid ? query (ls, l, mid, x) : query (rs, mid + 1, r, x));
}
#undef ls
#undef rs
#undef mid
} seg;
int n, m, q, len;
int ans[N], f[N];
struct Que {
int t, x, k, type;
} que[N << 1];
inline bool cmp (Que a, Que b) {
return a.x == b.x ? a.type < b.type : a.x < b.x;
}
void solve (int l, int r, int L, int R) {
int mid = (L + R) >> 1, now = 0;
vector <Que> ls, rs;
for (int i = l; i <= r; i++)
if (que[i].type)
if (now >= que[i].k) ans[que[i].t] = mid, ls.pb (que[i]);
else que[i].k -= now, rs.pb (que[i]);
else
if (que[i].t <= mid) now += que[i].k, ls.pb (que[i]);
else rs.pb (que[i]);
int i = l;
for (Que x : ls) que[i++] = x;
for (Que x : rs) que[i++] = x;
if (L == R) return;
solve (l, l + ls.size () - 1, L, mid), solve (l + ls.size (), r, mid + 1, R);
}
signed main () {
ios :: sync_with_stdio (false), cin.tie (0), cout.tie (0), cin >> n >> m >> q;
for (int i = 1, opt, l, r, x, y; i <= q; i++) {
cin >> opt;
if (opt == 1) cin >> l >> r >> x >> y, bit.add (l, y), bit.add (r + 1, -y), seg.update (1, 1, n, l, r, y), que[++len] = (Que) {i, l, y, 0}, que[++len] = (Que) {i, r + 1, -y, 0}, f[i] = x;
if (opt == 2) cin >> l >> r >> x, seg.update (1, 1, n, l, r, -x);
if (opt == 3) cin >> x >> y, que[++len] = (Que) {i, x, bit.sum (x) - seg.query (1, 1, n, x) + y, 1};
}
que[++len] = (Que) {q + 1, 1, INF, 0}, sort (que + 1, que + 1 + len, cmp), solve (1, len, 1, q + 1);
for (int i = 1; i <= q; i++) if (ans[i]) cout << (ans[i] < i ? f[ans[i]] : 0) << endl;
return 0;
}