序列树 & 贪心 & 考核补题

CTGU ACM集训队第二次月考核 C题 序列树

涉及算法 贪心

题目描述

在O. michestep王国,有一棵名叫Habaritran的树,树上有一个长度为 n 的序列 a,由于树的营养不足,序列只由 0 和 1 构成,修理工Mitchell mitt觉得序列中每个连续的长度为 k 的子串中的0 与1 数量都相同,这棵树才看起来很nice。当然,修理工Mitchell mitt可以将序列中任何一个 0 修改成 1,也可以将任何一个1修改为0,请问修理工Mitchell mitt最少需要修改多少次,才能将这棵树变得nice。

输入

第一行包含两个正整数,分别为 n和k
第二行包含 n个数,每个数为 0 或者 1

输出

输出一行包含一个正整数,表示最少次数,如果序列怎么修改都不能让这棵树变nice,那么输出"-1"(不包含引号)

样例输入

8 3
10100010

样例输出

-1

数据范围

1 <= k <= n <= 10^6

解题思路
在这里插入图片描述
贪心的思想主要集中在 “按b-a升序排序”, 也不难理解, 为了使修改次数最少, 排序后前半部分a比较大, 所以取b, 后半部分b比较大, 所以取a, 以此来使修剪次数最少。

附上一版我的AC代码:

#include<iostream>
#include<algorithm>
using namespace std;

int n, k;
char shu[1000000+10];
int cnt;
struct point{
	int cha;
	int a;
	int b;//a表示改成1,b表示改成0
};
typedef struct point P;
P biao[1000000+10];

bool cmp(point x, point y)
{
	return x.cha < y.cha; 
}

int main()
{
	scanf("%d%d ", &n, &k);
	for(int i=1;i<=n;i++)
		scanf("%c", &shu[i]);
	if(k%2!=0) {
		printf("-1");
	}else {
		for(int i=1;i<=k;i++){
			for(int j=i;j<=n;j+=k){
				if(shu[j]=='0') (biao[i].a)++;
			}
			//求a的。
			for(int j=i;j<=n;j+=k){
				if(shu[j]=='1') (biao[i].b)++;
			}
			//求b的。 
			biao[i].cha = biao[i].b - biao[i].a;
		}
		
		sort(biao+1, biao+1+k, cmp);
		for(int i=1;i<=(k/2);i++){
			cnt+=biao[i].b;
		}
		for(int i=(k/2)+1;i<=k;i++){
			cnt+=biao[i].a;
		}
		
		printf("%d", cnt);
	}
	return 0;
 } 
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值