您的位置:首页 > 产品设计 > UI/UE

4658: rescue

2017-04-10 20:37 148 查看

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
- 1LL * (T
/ D - T[1] / D) * A << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: