CodeCraft-22 and Codeforces Round 795 (Div. 2) D
# 记录做题思路
D. Max GEQ Sum
题目:
思路:
使用单调栈,先找到对于a[i]左右两边满足时a[i]作为最大值的L[i],R[i],然后你会发现只要在这个区间里面存在L[i]<=l<i使得sm[i-1]-sm[l-1]>0,或者i<r<=R[i]使得sm[r]-sm[i]>0那么一定有一个范围使得a[i] < 这个范围的和,然后怎样找到这个使得l~i-1的值>0或者i+1~r>0的l,r呢?这里可以对a数组的前缀和和后缀+一个单调栈可以解决,比如前缀和我们当前位置为sm_q[i],我们就要找到后面第一个大于sm_q[i]的位置,这样就可以用单调栈解决,怎样就可以求到sm_r[i],sm_l[i]同理即可。
总结:
错误的思路,我以为固定一端比如i,找到j使得i~j的和最大然后只要在里面的最大值大于和就行了。然后
很神奇竟然跑了79个测试点,但这样是不对的比如
20
222770758 -675711961 165034044 -642750758 -883529460 -865620784 446003892 -214378236 68965542 -41638545 106791145 -627263674 669189770 -431963037 -444266038 -904708548 -513875909 676690807 -17002387 -279706831
9~13=176044238
9~11=134118142
很明显68965542 -41638545 106791145(9~11)肯定是错误的,但是对于整个数组来说最大是9~13,说明思路是有问题的。
代码:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
ll inf=0x3f3f3f3f3f3f3f3f;
void solve(){
ll n;cin>>n;
vector<ll> a(n+1);
vector<ll> sm(n+1);
for(ll i=1;i<=n;i++){
cin>>a[i];sm[i]=a[i];sm[i]+=sm[i-1];
}
vector<ll> l(n+1);
stack<pair<ll,ll>> stk;
for(ll i=1;i<=n;i++){
while(stk.size()&&stk.top().first<=a[i])stk.pop();
if(stk.size()){
l[i]=stk.top().second+1;
}else{
l[i]=1;
}
stk.push({a[i],i});
}
while(stk.size())stk.pop();
vector<ll> r(n+1);
for(ll i=n;i>=1;i--){
while(stk.size()&&stk.top().first<=a[i])stk.pop();
if(stk.size()){
r[i]=stk.top().second-1;
}else{
r[i]=n;
}
stk.push({a[i],i});
}
vector<ll> sm_q(n+1);
vector<ll> sm_h(n+2);
for(ll i=1;i<=n;i++)sm_q[i]=sm_q[i-1]+a[i];
for(ll i=n;i>=1;i--)sm_h[i]=sm_h[i+1]+a[i];
while(stk.size())stk.pop();
vector<ll> sm_l(n+1);
for(ll i=1;i<=n;i++){
while(stk.size()&&stk.top().first<=sm_h[i])stk.pop();
if(stk.size()){
sm_l[i]=stk.top().second;
}else{
sm_l[i]=0;
}
stk.push({sm_h[i],i});
}
while(stk.size())stk.pop();
vector<ll> sm_r(n+1);
for(ll i=n;i>=1;i--){
while(stk.size()&&stk.top().first<=sm_q[i])stk.pop();
if(stk.size()){
sm_r[i]=stk.top().second;
}else{
sm_r[i]=n+1;
}
stk.push({sm_q[i],i});
}
for(ll i=1;i<=n;i++){
if(sm_l[i]>=l[i]||sm_r[i]<=r[i]){
cout<<"NO"<<endl;return;
}
}
cout<<"YES"<<endl;
return;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _;cin>>_;
while(_--)solve();
return 0;
}