1. 程式人生 > >Bzoj3110: [Zjoi2013]K大數查詢

Bzoj3110: [Zjoi2013]K大數查詢

gpo 覆蓋 bzoj code name etc ref std eof

題面

Bzoj

Sol

整體二分
比較經典,練手題
每次的修改會影響一個區間,我用的是線段樹覆蓋

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(1e5 + 5);

IL ll Input(){
    RG ll x = 0, z = 1; RG char c = getchar();
    for(; c < '0'
|| c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z; } int n, m, ans[_], vis[_], tag[_ << 2]; ll sum[_ << 2], tmp[_]; struct Data{ int
l, r, c, id; } q[_], q1[_], q2[_]; IL void Modify(RG int x, RG int l, RG int r, RG int L, RG int R, RG int v){ sum[x] += (R - L + 1) * v; if(L == l && R == r){ tag[x] += v; return; } RG int mid = (l + r) >> 1; if(R <= mid) Modify(x << 1, l, mid, L, R, v); else
if(L > mid) Modify(x << 1 | 1, mid + 1, r, L, R, v); else Modify(x << 1, l, mid, L, mid, v), Modify(x << 1 | 1, mid + 1, r, mid + 1, R, v); } IL ll Query(RG int x, RG int l, RG int r, RG int L, RG int R, RG ll ad){ if(L == l && R == r) return sum[x] + ad * (r - l + 1); RG int mid = (l + r) >> 1; ad += tag[x]; if(R <= mid) return Query(x << 1, l, mid, L, R, ad); if(L > mid) return Query(x << 1 | 1, mid + 1, r, L, R, ad); return Query(x << 1, l, mid, L, mid, ad) + Query(x << 1 | 1, mid + 1, r, mid + 1, R, ad); } IL void Solve(RG int l, RG int r, RG int L, RG int R){ if(L > R) return; if(l == r){ for(RG int i = L; i <= R; ++i) ans[q[i].id] = l; return; } RG int mid = (l + r) >> 1, t1 = 0, t2 = 0; for(RG int i = L; i <= R; ++i) if(vis[q[i].id]) tmp[q[i].id] = Query(1, 1, n, q[i].l, q[i].r, 0); else if(q[i].c > mid) Modify(1, 1, n, q[i].l, q[i].r, 1); for(RG int i = L; i <= R; ++i) if(vis[q[i].id]){ if(tmp[q[i].id] >= q[i].c) q2[++t2] = q[i]; else q[i].c -= tmp[q[i].id], q1[++t1] = q[i]; } else{ if(q[i].c <= mid) q1[++t1] = q[i]; else q2[++t2] = q[i]; } for(RG int i = L; i <= R; ++i) if(!vis[q[i].id] && q[i].c > mid) Modify(1, 1, n, q[i].l, q[i].r, -1); for(RG int i = L, j = 1; j <= t1; ++i, ++j) q[i] = q1[j]; for(RG int i = L + t1, j = 1; j <= t2; ++i, ++j) q[i] = q2[j]; Solve(l, mid, L, L + t1 - 1); Solve(mid + 1, r, L + t1, R); } int main(RG int argc, RG char* argv[]){ n = Input(); m = Input(); RG int mn = 2147483647, mx = -mn; for(RG int i = 1; i <= m; ++i){ RG int op = Input(); q[i].l = Input(), q[i].r = Input(), q[i].c = Input(), q[i].id = i; if(op == 1) mx = max(mx, q[i].c), mn = min(mn, q[i].c); vis[i] = op == 2; } Solve(mn, mx, 1, m); for(RG int i = 1; i <= m; ++i) if(vis[i]) printf("%d\n", ans[i]); return 0; }

Bzoj3110: [Zjoi2013]K大數查詢