Winter Is Coming CodeForces - 747D

15 篇文章 0 订阅

点击打开链接

思路很简单 写起来真的很难受 比赛差点就没出。。

先统计冷天(零下)有多少 记为sum 这些天是必须装备冬日轮胎的

如果冬日轮胎的数量k不足 肯定撑不过去 输出-1

否则肯定可以熬过这些天 那么问题就可以转换成 先把k个冬日轮胎分配到冷天 剩余的(k-sum)个轮胎分配到热天

先假设现在只有sum个轮胎 正好够我们用(分到冷天)但是每经历一次冷天到热天或热天到冷天的变化都要换一次轮胎

题目要求最少换轮胎的次数 如果我们剩余的(k-sum)个轮胎足够分配到 两个冷天连续时间段之间的热天连续时间段的每一天 那么我们减少一次冷到热与一次热到冷的替换

从小到大sort一下 到不够填满一个时间段为止

 

最需要注意的是

1 统计热天时间段要从第一个冷天时间段之后开始

2 最后一个热天时间段 要分类 之后有没有冷天时间段是不一样的

   如果之后没有冷天 我们把这个热天时间段填满后只能减少一次更换

   如果还有冷天 那就没什么区别

   所以对时间段排序的依据就是 天数(所需轮胎数)/可减少次数 这个才是关键

 

#include <stdio.h>
#include <cstring>
#include <algorithm>
#define N 1e9
using namespace std;

struct node
{
    int w;
    int v;
    double rate;
};

node last[200010];
int v[200010],w[200010],pack[200010];
int day[200010];

int cmp(node n1,node n2)
{
    return n1.rate>n2.rate;
}

int main()
{
    int n,k,i;
    int num,sum,cnt,flag,ans,cur;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        sum=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&day[i]);
            if(day[i]<0) sum++;
        }
        if(sum>k)
        {
            printf("-1\n");
            continue;
        }
        else
        {
            k-=sum;
        }

        num=0,cnt=0,flag=-1;
        for(i=1;i<=n;i++)
        {
            if(day[i]<0)
            {
                if(flag==1)
                {
                    num++;
                    last[num].w=cnt;
                }
                flag=0;
            }
            else
            {
                if(flag==0)
                {
                    cnt=1,flag=1;
                }
                else if(flag==1)
                {
                    cnt++;
                }
            }
        }
        if(flag==1)
        {
            num++;
            last[num].w=cnt;
        }

        ans=0,cur=0;
        for(i=1;i<=n;i++)
        {
            if(ans==0)
            {
                if(day[i]<0)
                {
                    ans=1;
                    cur=-1;
                }
            }
            else
            {
                if(cur==-1&&day[i]>=0) ans++,cur=1;
                else if(cur==1&&day[i]<0) ans++,cur=-1;
            }
        }

        for(i=1;i<=num;i++)
        {
            last[i].v=2;
        }
        if(day[n]>=0) last[num].v--;
        for(i=1;i<=num;i++)
        {
            last[i].rate=(double)(last[i].v)/(double)(last[i].w);
        }
        sort(last+1,last+num+1,cmp);

        cnt=0;
        for(i=1;i<=num;i++)
        {
            if(k-last[i].w>=0)
            {
                k-=last[i].w;
                cnt+=last[i].v;
            }
        }
        printf("%d\n",ans-cnt);
    }
    return 0;
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值