4658: rescue

68 篇文章 0 订阅

4658: rescue

Time Limit: 20 Sec   Memory Limit: 256 MB
Submit: 47   Solved: 22
[ Submit][ Status][ Discuss]

Description

wyh8000很喜欢看书,特别是那种很容易死脑细胞的书。
wyh8000看书喜欢从第K页开始看起,然后看到第M页,但是wvh8000并不是有耐心的小盆友,他
只想快点完成看书任务,然后就可以去愉快的农别人了,于是他经常跳着看,但是他一次最多跳D页,
然后阅读那一页的内容,然后死掉A的脑细胞。当然如果那一页的内容他比较感兴趣,又会回复一定
的脑细胞。
好心的学长不希望看到wyh8000的脑细胞死光,你能帮助wvh8000死掉尽可能少的脑细胞吗?

Input

第一行五个非负整数K,M,D,A,N。
K,M,D,A如题目描述。N表示有N页wvh8000比较感兴趣。
接下来N行,每一行两个正整数,Ti,Bi。,表示当wvh8000阅读第Ti页时,能回复Bi的脑细胞。
l <= Bi,A,D≤10^9,l<N<105。0<=K<T1<T2<…<Tn<M <= 10^9。

Output

一个整数ans。表示能拯救的最多的脑细胞数,若最后还是损失则为负数。

Sample Input

0 10 4 10 2
3 10
8 5

Sample Output

-20
wyh8000从第0页开始看。
wyh8000跳到第3页,损失10脑细胞。
wyh8000阅读第3页,拯救10脑细胞。
wyh8000跳到第7页并阅读,损失10脑细胞。
wyh8000眺到第10页并阅读,损失10脑细胞。
学长最后无能为力,但是损失20是最优的策略,所以输出为-20。

HINT

Source

[ Submit][ Status][ Discuss]



有用的页数显然就是那N个关键页

定义f[i]:看到第i个关键页时,脑细胞最大剩余量

f[i] = max{f[k] - A * [(T[i] - T[k]) / D]} + B[i] (k = 1~i-1,[]为上取整)

注意到[(T[i] - T[j]) / D] 和 [T[i] / D] - [T[j] / D] 的值几乎是一样的(最多相差1)

当T[i] % D > T[j] % D后式的结果会比预期大1

所以将T[i]的值按照%D分类,转移的时候分两类用线段树维护max即可

注意到转换之后[T[i] / D] - [T[j] / D]是个差分的形式,所以加到最后中间项都抵消了

那么只需要最后减去A * ([M / D] - [K / D]),中间讨论是否差1即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<stack>
#define max(a,b) ((a) > (b) ? (a) : (b))
using namespace std;
 
const int N = 4;
const int maxn = 1E5 + 10;
typedef long long LL;
const LL INF = 1E16;
 
int n,m,K,D,cur = 1,T[maxn],B[maxn],w[maxn];
LL A,f[maxn],Max[maxn*N],ma[maxn];
 
inline void Build(int o,int l,int r)
{
    Max[o] = -INF;
    if (l == r) {ma[l] = -INF; return;}
    int mid = l + r >> 1;
    Build(o<<1,l,mid); Build(o<<1|1,mid+1,r);
}
 
inline void Modify(int o,int l,int r,int pos,LL now)
{
    Max[o] = max(Max[o],now);
    if (l == r) return; int mid = l + r >> 1;
    if (pos <= mid) Modify(o<<1,l,mid,pos,now);
    else Modify(o<<1|1,mid+1,r,pos,now);
}
 
inline LL Query(int o,int l,int r,int ql,int qr)
{
    if (ql <= l && r <= qr) return Max[o];
    int mid = l + r >> 1; LL ret = -INF;
    if (ql <= mid) ret = Query(o<<1,l,mid,ql,qr);
    if (qr > mid) ret = max(ret,Query(o<<1|1,mid+1,r,ql,qr));
    return ret;
}
 
inline int getint()
{
    char ch = getchar(); int ret = 0;
    while (ch < '0' || '9' < ch) ch = getchar();
    while ('0' <= ch && ch <= '9')
        ret = ret * 10 + ch - '0',ch = getchar();
    return ret;
}
 
int main()
{
    #ifdef DMC
        freopen("DMC.txt","r",stdin);
    #endif
     
    cin >> K >> m >> D >> A >> n;
    for (int i = 2; i <= n + 1; i++)
        T[i] = getint(),w[i] = getint(),B[i] = T[i] % D;
    B[1] = K % D; B[n + 2] = m % D;
    T[1] = K; T[n + 2] = m; n += 2;
    sort(B + 1,B + n + 1);
    for (int i = 2; i <= n; i++)
        if (B[i] != B[i - 1]) B[++cur] = B[i];
    Build(1,1,cur);
    int pos = lower_bound(B + 1,B + cur + 1,T[1] % D) - B;
    Modify(1,1,cur,pos,0); ma[pos] = 0;
    for (int i = 2; i <= n; i++)
    {
        pos = lower_bound(B + 1,B + cur + 1,T[i] % D) - B;
        LL x = Query(1,1,cur,pos,cur);
        LL y = pos == 1 ? -INF : Query(1,1,cur,1,cur - 1);
        f[i] = max(x,y - A) + 1LL * w[i];
        if (f[i] > ma[pos]) Modify(1,1,cur,pos,f[i]),ma[pos] = f[i];
    }
    cout << f[n] - 1LL * (T[n] / D - T[1] / D) * A << endl;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值