CodeForces 1691D (单调栈 区间最值/最大子区间和)

题意: 判断数组是否满足所有子数组满足:
image

  • 枚举最值,一个最值所控制的区间是左边和右边第一个比他大的数的位置的开区间。
  • 用这个区间的最大子区间和和最值比较
  • 最大子区间和可以用i到R-1的最大值减去L到i-1的最小值得到,也可以像大嘴猫吃金币那样求。
    http://acm.zzuli.edu.cn/problem.php?id=2892
#include<bits/stdc++.h>
//#include <bits/extc++.h>
using namespace std;
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);  
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define ull unsigned long long
#define li __int128_t
//#define int long long
const int N = 2e5 + 5;
const int M = 1e6 + 5;
const int mod = 998244353;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
ll a[N], pre[N], L[N], R[N];
ll f[N][30], F[N][30]; int n;
void ST_create(){
 for(int i=1;i<=n;i++){
   f[i][0]=pre[i];
 }
 int k=log2(n);
 for(int j=1;j<=k;j++){
   for(int i=0;i<=n-(1<<j)+1;i++){ // 注意从零开始
     f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
   }
 }
}
void ST_create1(){
 for(int i=1;i<=n;i++){
   F[i][0]=pre[i];
 }
 int k=log2(n);
 for(int j=1;j<=k;j++){
   for(int i=0;i<=n-(1<<j)+1;i++){
     F[i][j]=min(F[i][j-1],F[i+(1<<(j-1))][j-1]);
   }
 }
}
ll mx(int l,int r){
 int k=log2(r-l+1);
 return max(f[l][k],f[r-(1<<k)+1][k]);
}
ll mn(int l,int r){
 if( r == 0 ) return 0;
 int k=log2(r-l+1);
 return min(F[l][k],F[r-(1<<k)+1][k]);
}
void solve() {
 cin >> n;
 for ( int i = 1; i <= n; ++ i ) {
   cin >> a[i]; pre[i] = pre[i - 1] + a[i];
 }
 stack<int> st;
 for ( int i = 1; i <= n; ++ i ) {
   while( st.size() && a[st.top()] <= a[i] ) st.pop();
   if(st.size()) L[i] = st.top(); else L[i] = 0;
   st.push(i); 
 }
 while( st.size() ) st.pop();
 for ( int i = n; i >= 1; -- i ) {
   while( st.size() && a[st.top()] <= a[i] ) st.pop();
   if(st.size()) R[i] = st.top(); else R[i] = n + 1;
   st.push(i); 
 }
 ST_create(); ST_create1();

 for ( int i = 1; i <= n; ++ i ) {
   int r1 = R[i] - 1;
   int l1 = L[i];
   int de1 = mx( i, r1);
   if( mx( i, r1) - mn( l1, i - 1) > a[i] ) {
     cout << "NO" << '\n'; return;
   }
 }
 cout << "YES" << '\n';
 for ( int i = 1; i <= n; ++ i ) pre[i] = 0;
}
int main() {
 int t; cin >> t;
 while( t -- ) solve();
 return 0;
}
posted @ 2022-06-01 16:08  qingyanng  阅读(83)  评论(0编辑  收藏  举报