CF1691D Max GEQ Sum
<h2>思路</h2>
- 考虑 $a_i$ 作为最大值的区间 $[l,r]$。
- 在 $[l,r]$ 中如果存在一段包含 $a_i$ 的连续和大于 $a_i$,则判断为 $\texttt{NO}$;如果对于所有 $a_i$ 都不存在这样的连续和,则为 $\texttt{YES}$。
实现
- 单调栈。
- 求最大连续和,由于必须包含 $a_i$,则在 $[i,r]$ 中寻找最大数,在 $[l-1,i-1]$ 中寻找最小数,两者之差就是最大和。
最大数、最小数的查找使用 st 表。
注:由于查询区间包含位置 $0$,st 表的建立需要从 $0$ 开始。
Code
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN=2e5+5; const ll INF=0x7ffffffffffffff; int t,n,l[MAXN],r[MAXN]; ll a[MAXN],sum[MAXN]/前缀和/,st1[MAXN][20]/区间最大值/,st2[MAXN][20]/区间最小值/; stack<int>s/单调栈/; ll get_max(int l,int r) { int k=log2(r-l+1); return max(st1[l][k],st1[r-(1<<k)+1][k]); } ll get_min(int l,int r) { int k=log2(r-l+1); return min(st2[l][k],st2[r-(1<<k)+1][k]); } int main() { cin>>t; while(t--) { bool flag=true; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; sum[i]=sum[i-1]+a[i]; st1[i][0]=st2[i][0]=sum[i]; } for(int j=1;(1<<j)<=n;j++)//st 表初始化 { for(int i=0;i+(1<<j)-1<=n;i++) { st1[i][j]=max(st1[i][j-1],st1[i+(1<<(j-1))][j-1]); st2[i][j]=min(st2[i][j-1],st2[i+(1<<(j-1))][j-1]); } } s.push(0); a[0]=INF; for(int i=1;i<=n;i++) { while(!s.empty()&&a[i]>=a[s.top()])s.pop(); l[i]=s.top()+1; s.push(i); } s.push(n+1); a[n+1]=INF; for(int i=n;i>=1;i--) { while(!s.empty()&&a[i]>=a[s.top()])s.pop(); r[i]=s.top()-1; s.push(i); } for(int i=1;i<=n;i++) { ll mx=get_max(i,r[i]); ll mn=get_min(l[i]-1,i-1); if(a[i]<mx-mn) { cout<<"NO\n"; flag=false; break; } } if(flag)cout<<"YES\n"; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!