codeforces 747D Winter Is Coming

这个题目比赛的时候想了好久,也没有做出来,当时想是个dp或者贪心,想着贪心的题目,dp应该也能做,所以就一直在dp上想,但是没有解决办法。今天有空就看了看这个题目。codeforces给的标签是贪心,自己就往贪心上想了想,最后解决了。其实用贪心的话并不难想,先判断是否可以度过整个冬天,这个比较简单就不再多说了。假设每次遇到0下的天气都需要换成冬天用的轮胎,而用完这一天之后就换成夏天用的轮胎,这样的话最大的交换次数就是2*c(c表示温度为0下的天数)。然后,记录相邻两个气温小于0度的天气之间相隔的天数和冬用的轮胎数大于温度为0下的天气的数量tmp。然后根据相隔天数从小往大贪心,当相隔的天数小于tmp时,交换的次数减2。最后注意判断如果 n - 最后一次出现0下的日期小于tmp的话,最终结果减1。说到dp,后来看了网上也有人用dp来做,将这个问题转化成了0-1背包的问题。这种想法真的值的学习。下面放上我写的贪心的代码。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAX = 200010;

struct Node{
	int u, x, y;
	bool operator < (const Node& args) const{
		return u < args.u;
	}
}p[MAX];

int a[MAX];

int main(int argc, char const *argv[])
{
	/* code */

	int n, k;
	while (scanf("%d%d", &n,&k) != EOF){

		int c = 0, l = 0, r = 0, cnt = 0;
		for (int i = 1; i<=n; i++){
			scanf("%d", &a[i]);
			if (a[i] < 0){
				c++;

				if (l == 0){
					l = i;
				}else{
					r = i;
					p[cnt++] = (Node){r-l-1, l, r};
					l = r;
				}
			}
		}



		if (c > k){
			printf("-1\n");
			continue;
		}else if (c == 0){
			printf("0\n");
			continue;
		}

		int last = r == 0 ? n-l : n - r;


		sort(p, p+cnt);
/*
		for (int i = 0; i<cnt; i++){
			printf("%d %d %d\n", p[i].u, p[i].x, p[i].y);
		}
*/
		int tmp = k - c;

		int res = c * 2;

		for (int i = 0; i<cnt; i++){
			if (p[i].u <= tmp){
				tmp -=  p[i].u;
				res -= 2;
			}
		}

		if (tmp >= last){
			res -= 1;
		}

		printf("%d\n", res);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CodeForces - 616D是一个关于找到一个序列中最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段中不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]中不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当前数字在map中不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]中的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值