1821D - Black Cells(暴力贪心枚举)

发布时间 2023-06-01 21:37:30作者: xxj112

大意加思路:相当于有一个绳子,其中有n段可以上色,如果要给一段上色代价增加2,没向前走一步代价加一,可以看出代价最多可以去对掉长度为一的段落,因为最后要给x个点上色代价做少为x,而前面的段落给1个点上色代价最少为2,另外要考虑最后一段可能没有完全上色。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PLL;
#define IOS cin.tie(nullptr)->sync_with_stdio(false);
#define se second
#define mem(a,b) memset(a,b,sizeof a);
#define pri priority_queue<int,vector<int>,greater<int> >
#define low(a,b,c) lower_bound(a,a+b,c)-a;
#define upp(a,b,c) upper_bound(a,a+b,c)-a;
//const int N=1e6+7;
LL mod = (int)1e9 + 7;
const int INF=0x3f3f3f3f;

void solve()
{
	int n,k;
	cin>>n>>k;
	vector<int> l(n),r(n);
	for(int i=0;i<n;i++) cin>>l[i];
	for(int j=0;j<n;j++) cin>>r[j];
	int ans=INF;
	int sum=0;
	int cnt1=0;
	for(int i=0;i<n;i++){
		int len=r[i]-l[i]+1;//当前段落的长度 
		cnt1+=(len==1); //段长为1的段数 
		sum+=len;//目前所有段的总长 
		if(sum>=k){//总长的个数 
			int remain=sum-k; //可以减去的段数 
			int res=r[i]-remain+2*(i+1)-min(remain,cnt1); //当前的花费 
//			if(cnt1>=remain)
//			{
//				res=r[i]+2*(i+1-remain);
//			} 
//			else
//			{
//				res=r[i]+2*(i+1-cnt1);
//				res-=min(remain-cnt1,len);
//			}
			//每次先考虑减去 前面 长度为1的段落,再减去 最后一段多余的点数 
			ans=min(ans,res); 
		}
	}
	if(ans==INF) ans=-1;
	cout<<ans<<"\n";
}
signed main()
{
	IOS;
	int t=1;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}



#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PLL;
#define IOS cin.tie(nullptr)->sync_with_stdio(false);
#define se second
#define mem(a,b) memset(a,b,sizeof a);
#define pri priority_queue<int,vector<int>,greater<int> >
#define low(a,b,c) lower_bound(a,a+b,c)-a;
#define upp(a,b,c) upper_bound(a,a+b,c)-a;
//const int N=1e6+7;
LL mod = (int)1e9 + 7;
const int INF=0x3f3f3f3f;

void solve()
{
	int n,k;
	cin>>n>>k;
	vector<int> l(n),r(n);
	for(int i=0;i<n;i++) cin>>l[i];
	for(int j=0;j<n;j++) cin>>r[j];
	int ans=INF;
	int sum=0;
	int cnt1=0;
	for(int i=0;i<n;i++){
		int len=r[i]-l[i]+1;//当前段落的长度 
		cnt1+=(len==1); //段长为1的段数 
		sum+=len;//目前所有段的总长 
		if(sum>=k){//总长的个数 
			int remain=sum-k; //可以减去的段数 
			int res=r[i]-remain+2*(i+1)-min(remain,cnt1); //当前的花费 
//			if(cnt1>=remain)
//			{
//				res=r[i]+2*(i+1-remain);
//			} 
//			else
//			{
//				res=r[i]+2*(i+1-cnt1);
//				res-=min(remain-cnt1,len);
//			}
			//每次先考虑减去 前面 长度为1的段落,再减去 最后一段多余的点数 
			ans=min(ans,res); 
		}
	}
	if(ans==INF) ans=-1;
	cout<<ans<<"\n";
}
signed main()
{
	IOS;
	int t=1;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}