1. 程式人生 > 其它 >CodeCraft-22 and Codeforces Round #795

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;
}