1 条题解
-
1
看到此题,首先想到前缀和。
然后我们贪心地去想
枚举每一个左端点 ,然后二分去第一个满足区间和大于等于 的右端点 ,接下来考虑对于每一个左端点,一定是满足最靠近 中的最大值最小,因为我们 要么比当前最大值大,那么答案就不优了,要么比当前最大值小,那么答案就还是当前的答案,所以说只用枚举每一个左端点,二分一个 让 再使用st表配合 求出区间最大值
时间复杂度
#include<iostream> #include<cstdio> #include<cmath> #define int long long using namespace std; bool Test_MLE_start; const int N=1e5+10; int T=1,n,m,ans=2e18; int a[N],b[N],sum[N]; int f[N][25]; bool Test_MLE_end; inline int reads(){ char c=getchar(); int sum=0,f=1; while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ sum=(sum<<3)+(sum<<1)+(c-'0'); c=getchar(); } return sum*f; } inline void files(){ freopen("std.in","r",stdin); freopen("std.out","w",stdout); } int asks(int l,int r){ if(l>r) return 2e18; int k=log(r-l+1)/log(2); return max(f[l][k],f[r-(1<<k)+1][k]); } bool check(int l,int r){ return sum[r]-sum[l-1]>=m; } int finds(int now){ int L=now,R=n,ret=0; while(L<=R){ int mid=(L+R)>>1; if(check(now,mid)){ ret=mid; R=mid-1; } else L=mid+1; } return ret; } signed main(){ // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // T=reads(); while(T--){ n=reads(),m=reads(); for(int i=1;i<=n;i++) a[i]=reads(),f[i][0]=b[i]=reads(); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; for(int j=1;j<=21;j++){ for(int i=1;i<=n-(1<<j)+1;i++){ f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]); } } for(int i=1;i<=n;i++){ int x=finds(i); ans=min(ans,asks(i,x)); } printf("%lld\n",ans); } return 0; } /* 5 10 4 8 6 9 3 5 4 6 3 7 */
- 1
信息
- ID
- 54
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 26
- 已通过
- 8
- 上传者