Codeforces Round #387(Div. 2)D. Winter Is Coming【思维+dp】

351 篇文章 2 订阅

D. Winter Is Coming
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

The winter in Berland lasts n days. For each day we know the forecast for the average air temperature that day.

Vasya has a new set of winter tires which allows him to drive safely no more than k days at any average air temperature. After k days of using it (regardless of the temperature of these days) the set of winter tires wears down and cannot be used more. It is not necessary that these k days form a continuous segment of days.

Before the first winter day Vasya still uses summer tires. It is possible to drive safely on summer tires any number of days when the average air temperature is non-negative. It is impossible to drive on summer tires at days when the average air temperature is negative.

Vasya can change summer tires to winter tires and vice versa at the beginning of any day.

Find the minimum number of times Vasya needs to change summer tires to winter tires and vice versa to drive safely during the winter. At the end of the winter the car can be with any set of tires.

Input

The first line contains two positive integers n and k (1 ≤ n ≤ 2·105, 0 ≤ k ≤ n) — the number of winter days and the number of days winter tires can be used. It is allowed to drive on winter tires at any temperature, but no more than k days in total.

The second line contains a sequence of n integers t1, t2, ..., tn ( - 20 ≤ ti ≤ 20) — the average air temperature in the i-th winter day.

Output

Print the minimum number of times Vasya has to change summer tires to winter tires and vice versa to drive safely during all winter. If it is impossible, print -1.

Examples
Input
4 3
-5 20 -3 0
Output
2
Input
4 2
-5 20 -3 0
Output
4
Input
10 6
2 -5 1 3 0 0 -4 -3 1 0
Output
3
Note

In the first example before the first winter day Vasya should change summer tires to winter tires, use it for three days, and then change winter tires to summer tires because he can drive safely with the winter tires for just three days. Thus, the total number of tires' changes equals two.

In the second example before the first winter day Vasya should change summer tires to winter tires, and then after the first winter day change winter tires to summer tires. After the second day it is necessary to change summer tires to winter tires again, and after the third day it is necessary to change winter tires to summer tires. Thus, the total number of tires' changes equals four. 


题目大意:

一共有N天,每天的气温已经给出,对应我们有两种轮胎,一种是冬季轮胎,一种是夏季轮胎,冬季轮胎可以在任何温度下使用,但是只能一共用K天(K天不必连续);

夏季轮胎只能在温度>=0的时候使用,没有限制天数。初始的时候是夏季轮胎

对应想要知道能不能度过整个冬天,如果可以,那么输出最少交换轮胎的次数,否则输出-1.


思路:


对于思维考虑阶段:

①对于负数的天的总数进行统计,记做cnt,如果cnt>k,那么无论怎么分配轮胎使用的情况,都是肯定度过不了这N天的,所以这种情况输出-1.

②我们肯定这样一点,对于初始温度大于等于0的连续那几天,我们可以不进行考虑,一直使用夏季轮胎即可。

③那么我们此时遇到的第一个小于0的温度的天的时候,是肯定需要进行轮胎替换行为的。

④对于连续小于0的几天,我们肯定不能进行轮胎替换工作,因为这几天我们只能用冬季轮胎。

⑤那么我们首先考虑怎样度过这N天最能节省冬季轮胎使用情况,那么我们肯定是对于连续的负数天使用冬季轮胎,对于连续的大于等于0的天使用夏季轮胎。

⑥那么我们预处理出一个数组b【i】,其中保存的是对应同类型的天连续的数量。

比如样例3(最前边的连续的大于等于0的天我们进行省略不考虑,因为那几天都直接使用夏季轮胎即可):

b【0】,b【1】,b【2】,b【3】

1 4 2 2

⑦对于我们预处理出来的b【】数组的长度,就是我们如果节省冬季轮胎使用情况下的需要交换的次数。接下来我们考虑如何节省交换次数,我们此时剩余k-cnt天可以使用冬季轮胎,那么我们考虑将相邻的区间进行合并.假如我们此时能够将那4天都使用冬季轮胎,那么很明显我们可以省去两次交换轮胎的操作,如果我们此时能够将那2天都使用冬季轮胎,那么很明显我们可以省去一次交换轮胎的操作。

⑧那么对应我们现在可以将问题转化为:我们有一个k-cnt容量的背包,其中b【i】数组中,i%2==1的位子上的区间长度是物品的体积,对应省去的交换轮胎的操作的次数就是价值,那么我们此时就将问题转化成了01背包问题。

⑨对于物品的处理也不难,对应我们观察,只有i%2==1&&i是最后一个区间的时候,对应的价值才是1,其余位子的物品价值都是2.

那么我们接下来只要跑一遍01背包,使其val值最大即可。


ans=b数组的长度-dp【k-cnt】;


Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
    int len,val;
}c[400500];
int a[400500];
int b[400500];
int dp[400500];
int cmp(node a,node b)
{
    if(a.len!=b.len)return a.len<b.len;
    else return a.val>b.val;
}
int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        int cnt=0;
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]<0)cnt++;
        }
        if(cnt>k)
        {
            printf("-1\n");
            continue;
        }
        int pos=n+1;
        for(int i=1;i<=n;i++)
        {
            if(a[i]<0)
            {
                pos=i;
                break;
            }
        }
        int contz=-1;
        int d=-1;
        for(int i=pos;i<=n;i++)
        {
            if(a[i]<0&&a[i-1]>=0)
            {
                contz++;
                b[contz]=1;
            }
            if(a[i]>=0&&a[i-1]<0)
            {
                contz++;
                b[contz]=1;
            }
            if(a[i]>=0&&a[i-1]>=0)b[contz]++;
            if(a[i]<0&&a[i-1]<0)b[contz]++;
        }
        int yu=k-cnt;
        int tmp=0;
        int output=contz+1;
        for(int i=0;i<=contz;i++)
        {
            if(i%2==1)
            {
                c[tmp].len=b[i];
                if(i!=contz)
                c[tmp++].val=2;
                if(i==contz)
                c[tmp++].val=1;
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<tmp;i++)
        {
            for(int j=yu;j>=c[i].len;j--)
            {
                dp[j]=max(dp[j],dp[j-c[i].len]+c[i].val);
            }
        }
        printf("%d\n",output-dp[yu]);
    }
}










  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值