Problem - D - Codeforceshttps://codeforces.com/contest/1691/problem/D
思考区间最大值然后求反例的时间复杂度肯定是不行的,所以我们可以思考求a[i]左边第一个大于它的和右边第一个大于它的,这样就可以使l[i]+1-r[i]-1这一段区间内a[i]最大,然后在[i,R[i]-1]这一段找最大前缀和,在[L[I],I-1]找最小前缀和,这样就可以求得包含a[i]的最大和。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cmath>
#include <cstring>
#include <string>
#define lowbit(x) ((x)&(-x))
using namespace std;
const int MAXN = 1e6 + 5;
using ll = long long ;
using ull = unsigned long long ;
const int INF=0x3f3f3f3f;
const ll NNF = 0x3f3f3f3f3f3f3f3f;
int n;
ll a[MAXN];
ll pre[MAXN];
struct node {
int l, r;
ll mx, mn;
} tr[MAXN];
ll R[MAXN];
ll L[MAXN];
ll stk[4 * MAXN];
int top;
void push_up(int q) {
tr[q].mx = max(tr[q << 1].mx, tr[q << 1 | 1].mx);
tr[q].mn = min(tr[q << 1].mn, tr[q << 1 | 1].mn);
}
void build(int q, int l, int r) {
if (l == r)
return void(tr[q] = node{l, l, pre[l], pre[l]});
tr[q] = node{l, r, 0, 0};
int mid = l + r >> 1;
build(q << 1, l, mid);
build(q << 1 | 1, mid + 1, r);
push_up(q);
}
ll query1(int q, int l, int r) {
if (tr[q].l >= l && tr[q].r <= r)
return tr[q].mx;
ll ans = -NNF;
int mid = tr[q].l + tr[q].r >> 1;
if (mid >= l)
ans = query1(q << 1, l, r);
if (mid < r)
ans = max(query1(q << 1 | 1, l, r), ans);
return ans;
}
ll query2(int q, int l, int r) {
if (tr[q].l >= l && tr[q].r <= r)
return tr[q].mn;
ll ans = NNF;
int mid = tr[q].l + tr[q].r >> 1;
if (mid >= l)
ans = query2(q << 1, l, r);
if (mid < r)
ans = min(ans, query2(q << 1 | 1, l, r));
return ans;
}
void solve() {
// stack<ll> st;
scanf("%d", &n);
stk[top = 0] = 0;
for (int i = 1; i <= n; i++) {
scanf("%lld", a + i);
pre[i] = pre[i - 1] + a[i];
// printf("%lld ", pre[i]);
}
// pre[n+1]=pre[n];
// putchar('\n');
build(1, 0, n);
for (int i = 1; i <= n; i++) {
while (top && a[stk[top]] <= a[i])
top--;
L[i] = stk[top];
// printf("%d ", L[i]);
stk[++top] = i;
}
stk[top = 0] = n + 1;
for (int i = n; i; i--) {
while (top && a[stk[top]] <= a[i])
top--;
R[i] = stk[top];
// printf("%d ", R[i]);
stk[++top] = i;
}
// putchar('\n');
// bool flag = 1;
for (int i = 1; i <= n; i++) {
ll tmp1 = query1(1, i, R[i] - 1), tmp2 = query2(1, L[i], i - 1);
// printf("%lld-%lld(%lld) ", tmp1, tmp2, a[i]);
if (tmp1 - tmp2 > a[i])
return void(printf("NO\n"));
}
printf("YES\n");
return;
}
int main() {
int t;
scanf("%d", &t);
while (t--)
solve();
return 0;
}