思路排除
这题乍一看好像是二分答案,但仔细一看好像还不太对,毕竟1600,太板了也不太好。
如果这题考二分的话,题面可能是让你求这个v最大可以为多少,这个非常适合二分答案,但显然这题不是这么问的。
我看见以前qq群里有人问什么时候用二分答案(牛客最近一场小白月赛出了道这个),我个人的回答是,你看到一道觉得像的题,都可以想一想能不能用二分答案,然后想一想检查器好不好写?如果检查器复杂度太高(跑一遍就超时),或者检查器所需要的算法可以直接求出该题答案,那么就不太行。
有些时候你也不要对自己要求太高,什么看一眼就知道怎么做。一般来说出现这种情况要么这道题太板了,要么这道题相对于你来说太简单了,我个人认为遇到这种情况大概率这题都不太适合于你平时练习,反而是你要想一想才对于你有提升吧。
思路讲解
搞两个数组存一下,到该位置能有多少个蛋糕(一个从左到右,一个从右到左,以消除左向依赖以及右向依赖)
具体而言是这样的

那么,然后如果我们要知道Alice把 [l,r] 这块区域切给自己后,剩下的我怎么知道够不够分那?
L[],R[]现在就开始发挥作用了
剩下区间的蛋糕总数就是L[l-1]+R[r+1]
1 2 3 4 5 6
| inline bool check(int l,int r) { if(L[l-1]+R[r+1]<m) return false; return true; }
|
写好 check( ) 剩下的事就简单了,就是用双指针去遍历每种可能的区间,不断更新答案就好了(用的事Acwing的模版)
1 2 3 4 5 6
| for(int i=1,j=1;i<=n;++i) { while (check(i,j) && j<=n) { ans=max(ans,sumA[j]-sumA[i-1]); ++j; } }
|
AC代码
AC记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <bits/stdc++.h> #define int long long
using namespace std; const int N=static_cast<int>(2e5)+15; int T,n,m,v,A[N],sumA[N],L[N],R[N];
inline bool check(int l,int r) { if(L[l-1]+R[r+1]<m) return false; return true; }
signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>T; while (T--) { cin>>n>>m>>v; for(int i=0;i<=n+10;++i) A[i]=0,sumA[i]=0,L[i]=0,R[i]=0; for(int i=1;i<=n;++i) { cin>>A[i]; sumA[i]=A[i]+sumA[i-1]; } int curT=0; for(int i=1;i<=n;++i) { curT+=A[i]; if(curT>=v) curT=0,L[i]=L[i-1]+1; else L[i]=L[i-1]; } curT=0; for(int i=n;i>=1;--i) { curT+=A[i]; if(curT>=v) curT=0,R[i]=R[i+1]+1; else R[i]=R[i+1]; } if(L[n]<m) { cout<<-1<<endl; continue; } int ans=0; for(int i=1,j=1;i<=n;++i) { while (check(i,j) && j<=n) { ans=max(ans,sumA[j]-sumA[i-1]); ++j; } } cout<<ans<<endl; } return 0; }
|
心路历程(WA,TLE,MLE……)
最早我觉得是二分答案,但接着发现不对。
代码我就不放了,主要原因是这个分蛋糕的Alice不是这m个生物中的一个,如果这题考二分的话,题目可能让你求这个v最大可以为多少。
记得把数组开大点,前面提交out of bound 了

然后不要动不动return 0;
&& j≤n 是可以加的,虽然之后的i其实就进入不到这个while里了,但先前的i一定比之后的i更优秀在这种情况下(你想想看,r确定了,l越来越大,[l,r]越来越像,Alice份给自己的就越来越少)
