1286A

Garland

题目出处

Problem - A - Codeforces

题目大意

给定一长度为 \(n\) 的序列,其中有一些已经填好了。要求用还没填上 \(1 \sim n\) 的数字填入序列,从而最小化序列中相邻但奇偶性不同的数对数量。

知识点、思路

贪心

具体想法、推导

显然我们可以只关注每个数的奇偶性,分别处理出可填的奇偶数的数量。

首先,把没有填好的连续的位置看成一个区间是比较自然的想法,对于一个区间,我们可以思考最好的填入方法。

我们可以把区间分成三类,用点表示没有填入的数,\(1/0\)表示区间边界的值的奇偶性:

第一类是形如 \(...... 1\) 和 $ 0 ......$ 的区间,即只有一侧有边界,显然都填入与边界相同奇偶性的数可以使得答案减 \(1\)

第二类是形如 \(1 ......1\)\(0 ......0\) 的区间,即区间两侧都有边界,且两侧边界奇偶性相同。显然都填入与边界相同奇偶性的数可以使得答案减 \(2\)

第三类是形如 \(1 ......0\)\(0 ......1\) 的区间,即区间两侧都有边界,且两侧边界奇偶性不同。此时可以发现,要填入一个数,最好的方法就是靠近与它奇偶性相同的位置,填好之后形如 $1 1 1 1 1 0 0 0 $ ,无论要填入的数奇偶性如何,对于此类区间,始终使得答案加 \(1\)

因此,为了使答案值最小化,我们要先预处理出三类区间,并优先填入第二类区间,无法填入第二类区间后,再考虑填入第一类区间。关于同类区间的填入,显然是从长度从小到大的顺序可以使得填入的区间数最多,因此要对区间进行排序。并且可以发现,填入第一、二类区间时,填入奇数和填入偶数是独立开来的,可以分开计算。

示例代码

void solve()
{	
	cin>>n;
	int cnt1=n/2+(n%2),cnt2=n/2;
	for (int i=1;i<=n;i++){
		cin>>a[i];
		if (a[i]==0) {
			a[i]=-1;
			continue;
		}
		a[i]%=2;
		if (a[i]==1) cnt1--;
		else cnt2--;
	}
	if (n==1) {
		cout<<0<<endl;
		return;
	}
	if (cnt1+cnt2==n){
		cout<<1<<endl;
		return;
	}
	priority_queue<int,vector<int>,greater<int>> q1,q2; //小根堆
 
	int st=1,ed=n;
 
 
	while (st<=n&&a[st]<0) st++;
	while (ed>=1&&a[ed]<0) ed--;
	int ans=0;
	for (int i=st;i<=ed;i++){
		if (a[i]>=0) {
			if (i!=1&&a[i-1]>=0&&a[i]!=a[i-1]) ans++;
			continue;
		}
		int j=i;
		while (j<=ed&&a[j]<0) j++;
		j--;
		if (a[i-1]==a[j+1]&&a[i-1]==1) {
			q1.push(j-i+1);
		}
		else if (a[i-1]==a[j+1]&&a[i-1]==0){
			q2.push(j-i+1);
		}
		else ans++;
		i=j;
	}

	while (!q1.empty()&&cnt1>=q1.top()){
		cnt1-=q1.top();
		q1.pop();
	}
	while (!q2.empty()&&cnt2>=q2.top()){
		cnt2-=q2.top();
		q2.pop();
	}
	while (!q1.empty()) {
		q1.pop();ans+=2;
	}
	while (!q2.empty()){
		q2.pop();ans+=2;
	}
	if (a[st]==1&&st!=1) q1.push(st-1);
	else q2.push(st-1); 
	if (a[ed]==1&&ed!=n) q1.push(n-ed);
	else q2.push(n-ed);
	while (!q1.empty()&&cnt1>=q1.top()){
		cnt1-=q1.top();
		q1.pop();
	}
	while (!q2.empty()&&cnt2>=q2.top()){
		cnt2-=q2.top();
		q2.pop();
	}
	while (!q1.empty()) {
		q1.pop();ans+=1;
	}
	while (!q2.empty()){
		q2.pop();ans+=1;
	}
 
	cout<<ans<<endl;
}
posted @ 2023-05-18 17:07  小孙孙得到  阅读(23)  评论(0编辑  收藏  举报