菜菜猫猫虫的,今天是一道洛谷绿题,还是一道 的,这很明显是一道思维题,我没想到的是这题也是二分,我开始就是往复杂度上考虑,刚拿到题目,我其实是枚举了一下样例,发现了一些比较好的性质,比如如果无穷大的话,我们发现操作到最后就是个严格单调递减的序列,而且也可以吧将每一位变成最大值的次数给找出来,但是实现发现,次数不够的话,有时候并不是严格从后往前是最优解,可能会出现局部最优解,而且大于严格最优解,于是我看了题解。
md我一看题解发现,二分,二分,二分,啊啊啊啊啊啊,我为什么每天找的题都是二分,其实按道理我也应该可以想到的,这个思路相对我的而言应该是更暴力了,然后考虑的是包含了我考虑到的严格最优解这种特殊的情况,于是我大概整理了一下思路,时间复杂度是,我感觉我想的就是在扯淡,思路是我们二分一个,这个就是我们要让这个序列中某个元素变成所需的最小次数,那当然可以暴力枚举嘛,从开始枚举到,这里有个很坑的地方就是(最后一个数不能变),对每个数,我们将其变成所需要花费的最小次数,那么如果这个数本身比大,那么直接 ,否则我们枚举第二个循环,其作用就是从开始到,我们考虑一下,怎么样才能把当前这个数变成,那么就是要后面那个数,只要这个,那么即使当前,我们也可以延续到下一个数,使下一个数满足使前一个数满足条件的条件,因为只要,那么我们都可以改变这个数,但是如果了,还不成立,那么就说明我们不能把这个数变成,然后写代码时候要注意,很多坑的地方,比如在某个处,我们发现当前,那么循环可以直接断开,因为满足,只有当且仅当必须跑到最后,且还不满足条件的时候 我们才可以认为这个不成立,不能直接在中途就判断。(写了这么多,好累,)。然后循环每个,取最小值,记不能取,不然你会惊奇地发现,所有次数都是。如果这个最小值,那么说明可以更大,否则,就得变小,二分的时候用的是的模板。
代码
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int t,n,k;
using namespace std;
const int N=1010;
ll a[N],cnt[N],b[N];
bool check(ll m){
memcpy(b,a,sizeof a);
memset(cnt,0,sizeof cnt);
for(int i=1;i<n;i++){
if(b[i]>=m) return true;
bool ok=false;
for(int j=i;j<=n;j++){
if(j==n && b[j]<m-(j-i)){
cnt[i]=1e15;
}
if(b[j]>=m-(j-i)){
ok=true;
break;
}
else cnt[i]+=m-(j-i)-b[j];
}
if(!ok) cnt[i]=1e15;
}
ll cntt=1e16;
for(int i=1;i<n;i++){
cntt=min(cntt,cnt[i]);
//cout<<cnt[i]<<" ";
}
//cout<<endl;
if(cntt<=k) return true;
return false;
}
void solve(){
cin>>n>>k;
ll maxn=0;
for(int i=1;i<=n;i++){
cin>>a[i];
maxn=max(maxn,a[i]);
}
ll l=maxn,r=1e12;
while(l<r){
ll mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<r<<"\n";
}
int main(){
IOS;
cin>>t;
while(t--) solve();
}
坚持下去,一定能实现梦想的!