思路很简单 写起来真的很难受 比赛差点就没出。。
先统计冷天(零下)有多少 记为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;
}