http://codeforces.com/contest/887/problem/D
一个模特有两种活动。
① 拍照片,挣钱 a。 ②开演唱会,花费b
给定模特这两种工作的时间表。
模特可以选定一个时间举办一个座谈会,那么他拍照片的钱变c。开演唱会会花费d。
要求再模特座谈会之前和后len天 都不能赔钱。 要求你输出最小的座谈会天数。 没有输出-1.。
思路:枚举第i天作为 开始的茶话会的时间(茶话会是可以和当天其他的活动撞的,并且当天有影响),然后计算后len天是否有负数。
T了。
正确的写法类似尺取,维护正常天数的前缀和,再计算以i活动为初始,(i活动已经被影响了,因为要尽可能的早,所以时间再第i-
1个活动的 下一天就举办茶话会),长度问len的特殊天数的茶话会。
绿色部分是 茶话会举办的时间,i为第一个被影响的天数。红色部分为len。cf上很多的代码算的影响天数都是从i开始的,我深感不解
是某个大佬的证明?还是数据没有卡掉?
#include <bits/stdc++.h>
using namespace std;
/* 本来想写一个初级想法 超时一下再改的。
结果初级想法wa了一天。。
要类似尺取一样,
这道题有以下方向我没考虑到。
那就是 ① 举办talkshow的时间是马上的,可以和其他时间重合
② 如果以i为开始的话,那么开始talkshow的时间最短可以是 node[i-1]+1。
③ 如果以i为开头计算,如果不可行,再继续从i+1计算的话,着tm肯定不可行。
这tm就和匹配字符串一样,复杂度几乎是 n2
.最好的方法就是双指针维护 前缀和(小名叫尺取)。
方法。当i为开头的时候,维护一个前缀和。
当不可以的时候,减去 首部分的前缀和(在这道题中是替换cd为ab)
*/
typedef long long ll;
const int maxn=3e5;
struct{
ll kin,cos;
}node[maxn];
int n;
ll a,b,c,d,lim,sta;
int main()
{ while(~scanf("%d%lld%lld%lld%lld%lld%lld",&n,&a,&b,&c,&d,&sta,&lim)){
for(int i=0;i<n;i++){
scanf("%lld%d",&node[i].cos,&node[i].kin);
}
ll mn=1e17;
ll ans=sta;
ll sum2=0;
int now=0;
bool flag=false;
int kk;
for(int i=0;i<n;i++){
ll tt;
if(i==0)tt=0;
else tt=node[i-1].cos+1;//计算i活动第一个被影响时,茶话会开始的日期
while(now<n&&(node[now].cos-tt)<lim){
if(node[now].kin==0)
sum2-=d;
else
sum2+=c;
mn=min(sum2,mn);
now++;
}
if(mn+ans>=0){
flag=true;
kk=i;
if(kk==0)
printf("0\n");
else
printf("%lld\n",node[kk-1].cos+1);
break; }
if(node[i].kin==1){
mn-=c;
sum2-=c;
ans+=a;
}
else {
mn+=d;
sum2+=d;
ans-=b;
}
if(ans<0){
puts("-1");
flag=true;
break;
}
}
if(!flag)
printf("%lld\n",node[n-1].cos+1);
}
return 0;
}