【BZOJ3110】【LG3332】[ZJOI2013]K大數查詢
阿新 • • 發佈:2018-12-12
【BZOJ3110】【LG3332】[ZJOI2013]K大數查詢
題面
題解
和普通的整體分治差不多
用線段樹維護一下每個查詢區間內大於每次二分的值\(mid\)的值即可
然後再按套路做就行了
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; inline int gi() { register int data = 0, w = 1; register char ch = 0; while (ch != '-' && (ch > '9' || ch < '0')) ch = getchar(); if (ch == '-') w = -1 , ch = getchar(); while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar(); return w * data; } typedef long long ll; const int MAX_N = 50005; #define lson (o << 1) #define rson (o << 1 | 1) struct SGT { bool clr; int tag; ll val; void clear() { clr = 0, tag = val = 0; } } t[MAX_N << 2]; int N, M, ans[MAX_N]; void puttag(int o, int l, int r, int w) { t[o].val += 1ll * w * (r - l + 1); t[o].tag += w; } void clear(int o) { if (t[o].clr) { t[lson].clear(), t[rson].clear(); t[lson].clr = t[rson].clr = 1; t[o].clr = 0; } } void pushdown(int o, int l, int r) { if (l == r) return ; int mid = (l + r) >> 1; clear(o); puttag(lson, l, mid, t[o].tag); puttag(rson, mid + 1, r, t[o].tag); t[o].tag = 0; } void modify(int o, int l, int r, int ql, int qr) { if (ql <= l && r <= qr) return (void)puttag(o, l, r, 1); pushdown(o, l, r); int mid = (l + r) >> 1; if (ql <= mid) modify(lson, l, mid, ql, qr); if (qr > mid) modify(rson, mid + 1, r, ql, qr); t[o].val = t[lson].val + t[rson].val; } ll query(int o, int l, int r, int ql, int qr) { pushdown(o, l, r); if (ql <= l && r <= qr) return t[o].val; int mid = (l + r) >> 1; ll res = 0; if (ql <= mid) res += query(lson, l, mid, ql, qr); if (qr > mid) res += query(rson, mid + 1, r, ql, qr); return res; } struct Query { int op, x, y; ll z; } q[MAX_N], lq[MAX_N], rq[MAX_N]; void Div(int lval, int rval, int st, int ed) { if (st > ed) return ; if (lval == rval) { for (int i = st; i <= ed; i++) if (q[i].op != 0) ans[q[i].op] = lval; return ; } int mid = (lval + rval) >> 1; int lt = 0, rt = 0; for (int i = st; i <= ed; i++) { if (q[i].op == 0) { if (q[i].z <= mid) lq[++lt] = q[i]; else { rq[++rt] = q[i]; modify(1, 1, N, q[i].x, q[i].y); } } else { ll res = query(1, 1, N, q[i].x, q[i].y); if (res >= q[i].z) rq[++rt] = q[i]; else q[i].z -= res, lq[++lt] = q[i]; } } for (int i = 1; i <= lt; i++) q[i + st - 1] = lq[i]; for (int i = 1; i <= rt; i++) q[i + lt + st - 1] = rq[i]; t[1].clear(); t[1].clr = 1; Div(lval, mid, st, st + lt - 1); Div(mid + 1, rval, st + lt, ed); } int main () { int tot = 0; N = gi(), M = gi(); for (int i = 1; i <= M; i++) { q[i].op = gi() - 1; q[i].x = gi(), q[i].y = gi(), q[i].z = gi(); if (q[i].op) q[i].op = ++tot; } Div(-N, N, 1, M); for (int i = 1; i <= tot; i++) printf("%d\n", ans[i]); return 0; }