为了这道题学的st表
放个自己学的加从cf大佬代码上搞来的写了一块板子
st表和线段树功能很像,但st表是静态的,可以用来维护区间的最大,最小·,gcd,lcm
板子·
struct ST{//得到区间最小值最大值的稀疏表
int mi[N][20]={0},ma[N][20]={0};
inline int getmin(int l,int r){
if(l>r)return 0;
int k=log2(r-l+1);
return min(mi[l][k],mi[r-(1<<k)+1][k]);
}
inline int getmax(int l,int r){
if(l>r)return 0;
int k=log2(r-l+1);
return max(ma[l][k],ma[r-(1<<k)+1][k]);
}
void init(){
for(int i=1;i<=n;i++)ma[i][0]=mi[i][0]=sum[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=0;i+(1<<j)-1<=n;i++){//注意这里从0开始
mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
ma[i][j]=max(ma[i][j-1],ma[i+(1<<(j-1))][j-1]);
}
}
}st;
题意:判断一个数组的任意一段区间是否都满足所有数的和sum<=最大值max
卡住好多次拿一个大佬的代码一字一字对照,发现一开始自己写的板子也有点误差,还有处理单调栈时出了点小问题。
思路:对于这道题,显然是枚举最大值包含的区间,用单调·栈处理最长的一段区间,再用st表找前缀和里前面最小的值,后面最大的值,这样区间和一定是最大的。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
const int N=2e5+10;
int a[N],n,L[N],R[N],sum[N]={0};
struct ST{//得到区间最小值最大值的稀疏表
int mi[N][20]={0},ma[N][20]={0};
inline int getmin(int l,int r){
if(l>r)return 0;
int k=log2(r-l+1);
return min(mi[l][k],mi[r-(1<<k)+1][k]);
}
inline int getmax(int l,int r){
if(l>r)return 0;
int k=log2(r-l+1);
return max(ma[l][k],ma[r-(1<<k)+1][k]);
}
void init(){
for(int i=1;i<=n;i++)ma[i][0]=mi[i][0]=sum[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=0;i+(1<<j)-1<=n;i++){//注意这里从0开始
mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
ma[i][j]=max(ma[i][j-1],ma[i+(1<<(j-1))][j-1]);
}
}
}st;
signed main(){
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
stack<int> stk;
a[0]=1e9+10;
for(int i=0;i<=n;i++){
while(stk.size() &&a[stk.top()]<=a[i])stk.pop();//找最大区间
if(i!=0)L[i]=stk.top()+1;
stk.push(i);
}//找最近一个大于等于他的后一个
while(stk.size())stk.pop();
a[n+1]=1e9+10;
for(int i=n+1;i>=1;i--){
while(stk.size() && a[stk.top()]<=a[i])stk.pop();
if(i!=n+1)R[i]=stk.top()-1;
stk.push(i);
}//找最近一个大于等于他的前一个
sum[0]=0;
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
st.init();
bool flag=1;
for(int i=1;i<=n;i++){
//cout<<i<<" "<<R[i]<<" "<<L[i]<<endl;
int mi=st.getmin(L[i]-1,i-1);//注意可以是l[i]-1,前缀和啊
int ma=st.getmax(i,R[i]);
if(ma-mi>a[i]){
cout<<"NO"<<endl;
flag=0;
break;
}
}
if(flag)cout<<"YES"<<endl;
}
}