4658: rescue

来源:互联网 发布:抢小米 软件 编辑:程序博客网 时间:2024/05/18 12:44

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 0
原创粉丝点击