[POI 2009]Lyz
阿新 • • 發佈:2018-07-14
是否 cpp pac mat using 線段 pre code sca
Description
題庫鏈接
初始時滑冰俱樂部有 \(1\) 到 \(n\) 號的溜冰鞋各 \(k\) 雙。已知 \(x\) 號腳的人可以穿 \(x\) 到 \(x+d\) 的溜冰鞋。有 \(m\) 次操作,每次包含兩個數 \(r_i\) , \(x_i\) 代表來了 \(x_i\) 個 \(r_i\) 號腳的人。 \(x_i\) 為負,則代表走了這麽多人。 對於每次操作,輸出溜冰鞋是否足夠。
\(1\leq n\leq 200,000,1\leq m\leq 500,000\)
Solution
用 \(\text{Hall}\) 定理以及貪心的思想,容易得到 \(\forall l,r\in[1,n],l\leq r\)
\[\sum_{i=l}^rx_i\leq k(r+d-l+1)\]
移項,得到
\[\sum_{i=l}^r(x_i-k)\leq k\times d\]
顯然只要有 \((x_i-k)\) 最大子段和 \(\leq k\times d\) 。線段樹維護即可。
Code
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 200000+5; int n, m, k, d, x, r; struct node { ll mx, l, r, sum; node (ll _mx = 0, ll _l = 0, ll _r = 0, ll _sum = 0) { mx = _mx, l = _l, r = _r, sum = _sum; } node operator + (const node &b) const { node ans; ans.l = max(l, sum+b.l); ans.r = max(b.r, b.sum+r); ans.sum = sum+b.sum; ans.mx = max(r+b.l, max(mx, b.mx)); return ans; } } ; struct Segment_tree { #define lr(o) (o<<1) #define rr(o) (o<<1|1) node key[N<<2]; void build(int o, int l, int r) { if (l == r) {key[o] = node(-k, -k, -k, -k); return; } int mid = (l+r)>>1; build(lr(o), l, mid), build(rr(o), mid+1, r); key[o] = key[lr(o)]+key[rr(o)]; } void modify(int o, int l, int r, int loc, int val) { if (l == r) { ll t = key[o].sum+val; key[o] = node(t, t, t, t); return; } int mid = (l+r)>>1; if (loc <= mid) modify(lr(o), l, mid, loc, val); else modify(rr(o), mid+1, r, loc, val); key[o] = key[lr(o)]+key[rr(o)]; } } T; void work() { scanf("%d%d%d%d", &n, &m, &k, &d); T.build(1, 1, n); while (m--) { scanf("%d%d", &r, &x); T.modify(1, 1, n, r, x); puts(T.key[1].mx <= 1ll*k*d ? "TAK" : "NIE"); } } int main() {work(); return 0; }
[POI 2009]Lyz