CF1856C To Become Max

63 阅读3分钟

Problem - 1856C - Codeforces

菜菜猫猫虫的Day4Day4,今天是一道洛谷绿题,还是一道CFCF div2div2CC,这很明显是一道思维题,我没想到的是这题也是二分,我开始就是往O(n)O(n)复杂度上考虑,刚拿到题目,我其实是枚举了一下样例,发现了一些比较好的性质,比如如果kk无穷大的话,我们发现操作到最后就是个严格单调递减的序列,而且也可以吧将每一位变成最大值的次数给找出来,但是实现发现,次数不够的话,有时候并不是严格从后往前是最优解,可能会出现局部最优解,而且大于严格最优解,于是我看了题解。

md我一看题解发现,二分,二分,二分,啊啊啊啊啊啊,我为什么每天找的题都是二分,其实按道理我也应该可以想到的,这个思路相对我的而言应该是更暴力了,然后考虑的是包含了我考虑到的严格最优解这种特殊的情况,于是我大概整理了一下思路,时间复杂度是O(n2logn)O(n^2logn),我感觉我想的O(n)O(n)就是在扯淡,思路是我们二分一个midmid,这个midmid就是我们要让这个序列中某个元素变成midmid所需的最小次数,那当然可以暴力枚举嘛,从11开始枚举到(n1)(n-1),这里有个很坑的地方就是(最后一个数不能变),对每个数,我们将其变成midmid所需要花费的最小次数,那么如果这个数本身比midmid大,那么直接returnreturn truetrue,否则我们枚举第二个循环,其作用就是从ii开始到nn,我们考虑一下,怎么样才能把当前这个数变成midmid,那么就是要后面那个数mid(ji)≥mid-(j-i),只要这个jnj≠n,那么即使当前aj<mid(ji)a_j<mid-(j-i),我们也可以延续到下一个数,使下一个数满足使前一个数满足条件的条件,因为只要n≠n,那么我们都可以改变这个数,但是如果=n=n了,还不成立,那么就说明我们不能把aia_i这个数变成midmid,然后写代码时候要注意,很多坑的地方,比如在某个jj处,我们发现当前ajmid(ji)a_j≥mid-(j-i),那么循环可以直接断开,因为满足,只有当且仅当必须跑到最后nn,且nn还不满足条件的时候 我们才可以认为这个不成立,不能直接在中途就判断。(写了这么多,好累,TATTAT)。然后循环每个cntcnt,取最小值,记不能取n,QAQn,QAQ,不然你会惊奇地发现,所有次数都是0(bushi)0(bushi)。如果这个最小值k≤k,那么说明可以更大,否则,就得变小,二分的时候用的是l+r+1>>1l+r+1>>1的模板。

代码

#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();
}

坚持下去,一定能实现梦想的!