CodeCraft-22 and Codeforces Round #795
阿新 • • 發佈:2022-06-01
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; }