CodeCraft-22 and Codeforces Round #795
CodeCraft-22 and Codeforces Round #795
D. Max GEQ Sum
题意:就是问是否对所有的pair都有这个式子成立\(max(a_i,a_{i+1},…,a_{j−1},a{j})≥a_i+a_{i+1}+⋯+a_{j−1}+a_{j}\)
做法:考虑对每一个a[i],当其是最大值时求一下是否有这个式子成立,而当其为最大值时,必然对于\(a[l]...a[i]<=a[i]\),\(a[i]<=a[i]...a[r]\),所以只需要找到每个a[i]对应的l,和r即可,这个可以分别从前后用单调栈做,然后对其中的所有l,r对求一个区间和的最大值,这个可以维护前缀和,我们知道前缀和相减就是区间和,那么对[l..i]维护一个前缀和最小值,[i...r]维护一个前缀和最大值即可,
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
ll a[maxn],sum[maxn];
ll f1[maxn][21],f2[maxn][21],sta[maxn];
int Log2[maxn];
void build1(int n){
for (int i = 0; i <= n; ++i)
f1[i][0] = sum[i];
for (int i = 1; i <= 20; ++i)
for (int j = 0; j + (1 << i) - 1 <= n; ++j)
f1[j][i] = max(f1[j][i - 1], f1[j + (1 << (i - 1))][i - 1]);
}
void build2(int n){
for (int i = 0; i <= n; ++i)
f2[i][0] = sum[i];
for (int i = 1; i <= 20; ++i)
for (int j = 0; j + (1 << i) - 1 <= n; ++j)
f2[j][i] = min(f2[j][i - 1], f2[j + (1 << (i - 1))][i - 1]);
}
ll getmax(int l,int r){
if(l>r) return -1e18;
int s = Log2[r - l + 1];
return max(f1[l][s], f1[r - (1 << s) + 1][s]);
}
ll getmin(int l,int r){
if(l>r) return 1e18;
int s = Log2[r - l + 1];
return min(f2[l][s], f2[r - (1 << s) + 1][s]);
}
int L[maxn],R[maxn];
int main(){
#ifdef lmj_debug
freopen("1.in","r",stdin);
#endif
int T;
cin>>T;
for (int i = 2; i <= maxn-10; ++i)
Log2[i] = Log2[i / 2] + 1;
while(T--){
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
build1(n),build2(n);
bool flag=0;
int top=0;
a[0]=1e18;
for (int i=1;i<=n;i++){
while(a[sta[top]]<=a[i]) top--;
L[i]=sta[top];
sta[++top]=i;
}
top=0;
for (int i=n;i>=1;i--){
while(a[sta[top]]<=a[i]) top--;
if(top==0) R[i]=n;
else R[i]=sta[top]-1;
// printf("%d %d %d %d %d\n",i,L[i],R[i],getmax(i,R[i]),getmin(L[i],i-1));
if(getmax(i,R[i])-getmin(L[i],i-1)>a[i]){
flag=1;
break;
}
sta[++top]=i;
}
if(flag) puts("NO");
else puts("YES");
}
return 0;
}