codeforces#round 795 D
阿新 • • 發佈:2022-06-05
D. Max GEQ Sum
要求所有的區間都滿足最大值大於區間和
思路:
考慮每一個數字在他的區間裡面的貢獻,假設x在L到R中是最大值,那麼要求l到r的最大子段和小於等於x就可以滿足條件,x左右第一個大於x的數可以使用單調棧求解,區間最大子段和使用線段樹
程式碼:
#include <bits/stdc++.h> #define int long long int _ = 0, Case = 1; using namespace std; #define all(v) begin(v),end(v) #define nline '\n' #define ls(x) x<<1 #define rs(x) x<<1 |1 #define N 500010 int a[N]; int life[N << 2]; struct tree { int l, r; int sum, lmax, rmax, smax; } tr[N << 2]; void pushup(tree &p, tree &l, tree &r) { p.sum = l.sum + r.sum; p.lmax = max(l.lmax, l.sum + r.lmax); p.rmax = max(r.rmax, r.sum + l.rmax); p.smax = max({l.smax, r.smax, l.rmax + r.lmax}); } void pushup(int p) { pushup(tr[p], tr[ls(p)], tr[rs(p)]); } void build(int p, int l, int r) { if (l == r) { tr[p] = {l, r, a[l], a[l], a[l], a[l]}; life[l] = p; } else { tr[p] = {l, r}; int mid = l + r >> 1; build(ls(p), l, mid); build(rs(p), mid + 1, r); pushup(p); } } void modify(int x, int y) { int t = x; x = life[x]; tr[x] = {t, t, y, y, y, y}; for (x >>= 1; x; x >>= 1) pushup(x); } tree query(int p, int l, int r) { if (tr[p].l >= l and tr[p].r <= r) return tr[p]; int mid = tr[p].l + tr[p].r >> 1; if (r <= mid) return query(ls(p), l, r); else if (l > mid) return query(rs(p), l, r); else { tree ret; auto left = query(ls(p), l, r); auto right = query(rs(p), l, r); pushup(ret, left, right); return ret; } } int l[N], r[N], n; void cal() { stack<int> stk; a[0] = 1e18; stk.push(0); for (int i = 1; i <= n; i++) { while (stk.size() and a[i] >= a[stk.top()]) stk.pop(); l[i] = stk.top(); stk.push(i); } } void cal1() { stack<int> stk; stk.push(n + 1); a[n + 1] = 1e18; for (int i = n; i >= 1; i--) { while (stk.size() and a[i] >= a[stk.top()]) stk.pop(); r[i] = stk.top(); stk.push(i); } } void solve(int Case) { scanf("%lld", &n); for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); l[i] = r[i] = 0; } build(1, 1, n); cal(), cal1(); bool ok = true; for (int i = 1; i <= n; i++) { int L = l[i], R = r[i]; L++, R--; if (a[i] < query(1, L, R).smax) ok = false; } if (ok) puts("Yes"); else puts("No"); } signed main() { for (scanf("%lld", &_), Case = 1; Case <= _; Case++) solve(Case); return 0; }