阅读

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  0 10 4 10 2
  3 10
  8 5

Sample Output

  -20

HINT

  

Main idea

  从K走向M,路上有n个收益点,表示到了pos位置可以增加val的收益,每次最多可以走D步,走一次损耗A。求最大收益。

Solution

  这题必然是一道DP,我们层层深入来思考。

  先从20%考虑:首先我们一下子就想到了暴力DP,令f[i]表示到了第i个收益点的最大收益,显然对于每个收益点我们可以O(n)往前枚举每种情况,两个收益点间到达的方法必然是每次都跳D步,最后补上一段,那么步数就是,这样做就是O(n^2)的算法。

  再考虑另外30%:我们发现,我们可以将pos%D同余的放在一个集合,因为这样的话两点之间到达必然是一直跳D步的,那么显然在同一个集合里的点最后一个点对后面的点贡献更优。由于这时候D<=100,我们先预处理,然后新增点的时候枚举D更新即可。

  考虑100%的做法:我们将前面两种方法结合起来,我们发现,由于中间这个步数是一个上取整的东西,不好维护,于是我们可以把它拆成,这个东西具体是+0还是+1我们可以举例子来思考。发现根据余数有关:当pos[j]%D<pos[i]%D的时候+1,否则+0。然后我们就可以用一个线段树来优化这个DP。对于叶子节点 i 维护 pos%D=i 的最值,这里的最值指的是上述式子中仅仅与 j 有关的一项,因为后面的val[i]以及其它项是都要加的,所以可以不管。然后我们再往线段树里面每次加入f[i],这样显然就是区间查询最值、单点修改的一个线段树结构。效率O(nlogn)

  这里还有一个技巧就是:所以我们维护线段树权值的时候可以不用管pos,最后对于答案加减操作即可。

  这样我们就解决了这道题\(≧▽≦)/。

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std; typedef long long s64;
const int ONE=;
const s64 INF=1e18; int K,M,D,A,n;
s64 F,res;
int pos[ONE],val[ONE];
int Mod;
int li[ONE],Num; struct power
{
s64 maxx;
}Node[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Build(int i,int l,int r)
{
Node[i].maxx = -INF;
if(l==r) return;
int mid=(l+r)>>;
Build(i<<,l,mid); Build(i<<|,mid+,r);
} void Update(int i,int l,int r,int L,s64 x)
{
if(l==r)
{
Node[i].maxx = max(Node[i].maxx,x);
return;
}
int mid=(l+r)>>;
if(L<=mid) Update(i<<,l,mid,L,x);
else Update(i<<|,mid+,r,L,x);
Node[i].maxx = max(Node[i<<].maxx , Node[i<<|].maxx);
} void Query(int i,int l,int r,int L,int R)
{
if(L > R) return;
if(L<=l && r<=R)
{
res=max(res,Node[i].maxx);
return;
}
int mid=(l+r)>>;
if(L<=mid) Query(i<<,l,mid,L,R);
if(mid+<=R) Query(i<<|,mid+,r,L,R);
} int main()
{
K=get(); M=get(); D=get(); A=get(); n=get();
for(int i=;i<=n;i++)
pos[i]=get(), val[i]=get();
pos[]=K; pos[++n]=M; for(int i=;i<=n;i++) li[++Num]=pos[i] % D;
sort(li+,li+Num+); Num=unique(li+,li+Num+) - li -; Build(,,Num);
Mod = lower_bound(li+,li+Num+, K%D) - li;
Update(,,Num,Mod,);
for(int i=;i<=n;i++)
{
F = -INF;
Mod = lower_bound(li+,li+Num+, pos[i]%D) - li; res=-INF; Query(,,Num,,Mod-); F=max(F, res - A + val[i] );
res=-INF; Query(,,Num,Mod,Num); F=max(F, res + val[i]); Update(,,Num, Mod,F);
} printf("%I64d",F + (s64)A*(K/D) - (s64)A*(M/D));
}

【Foreign】阅读 [线段树][DP]的更多相关文章

  1. Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    [题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...

  2. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  3. 【Foreign】划分序列 [线段树][DP]

    划分序列 Time Limit: 20 Sec  Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 9 4 ...

  4. lightoj1085 线段树+dp

    //Accepted 7552 KB 844 ms //dp[i]=sum(dp[j])+1 j<i && a[j]<a[i] //可以用线段树求所用小于a[i]的dp[j ...

  5. [CF 474E] Pillars (线段树+dp)

    题目链接:http://codeforces.com/contest/474/problem/F 意思是给你两个数n和d,下面给你n座山的高度. 一个人任意选择一座山作为起始点,向右跳,但是只能跳到高 ...

  6. HDU-3872 Dragon Ball 线段树+DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3872 题意:有n个龙珠按顺序放在一列,每个龙珠有一个type和一个权值,要求你把这n个龙珠分成k个段, ...

  7. HDU4521+线段树+dp

    题意:在一个序列中找出最长的某个序列.找出的序列满足题中的条件. 关键:对于 第 i 个位置上的数,要知道与之相隔至少d的位置上的数的大小.可以利用线段树进行统计,查询.更新的时候利用dp的思想. / ...

  8. Codeforces Round #343 (Div. 2) D - Babaei and Birthday Cake 线段树+DP

    题意:做蛋糕,给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和. 思路:首先离散化蛋糕体积,以蛋糕数量建树建树,每个节点维护最大值,也就是假如节点i放在最上层情况 ...

  9. Special Subsequence(离散化线段树+dp)

    Special Subsequence Time Limit: 5 Seconds      Memory Limit: 32768 KB There a sequence S with n inte ...

随机推荐

  1. 一次和别人争吵一个按钮,点击后显示导航;再点击不显示的效果,是否一定以及必须用js?

    事情经过是这样的,我们组一个说话很喜欢用一定,肯定的哥们,吃午饭的时候拿了自己做的一个UI库,头部有一个按钮 点击展开,再次点击收缩,他意思说一个按钮无法记录点击状态,必须使用js.然后我看了一眼,心 ...

  2. Scala学习笔记(二):运行脚本文件

    在某个目录(如:F:\)下新建一个文本文件,命名为:hello.scala 其内容为: println("Hello World!") 那么这个时候该怎么运行这个脚本文件呢? 通过 ...

  3. springmvc基础篇—使用注解方式为前台提供数据

    一.新建一个Controller package cn.cfs.springmvc.service; import java.util.ArrayList; import java.util.Hash ...

  4. python基础篇 08 文件操作

    本节主要内容:1. 初识⽂件操作2. 只读(r, rb)3. 只写(w, wb)4. 追加(a, ab)5. r+读写6. w+写读7. a+写读(追加写读)8. 其他操作⽅法9. ⽂件的修改以及另⼀ ...

  5. 为Zabbix配置Nova服务、Keystone和Placement进程CPU和内存usage监控

    目前已经完成了RabbitMQ和MySQL的监控项配置,还差对nova-api.nova-conductor.nova-scheduler和keystone进程CPU和内存 usage的监控,类似的轮 ...

  6. 深度可分卷积(Depthwise Separable Conv.)计算量分析

    上次读到深度可分卷积还是去年暑假,各种细节都有些忘了.记录一下,特别是计算量的分析过程. 1. 标准卷积和深度可分卷积 标准卷积(MobileNet论文中称为Standard Convolution, ...

  7. 软件工程项目组Z.XML会议记录 2013/09/18

    软件工程项目组Z.XML会议记录 [例会时间]2013年9月18日周三21:00-23:00 [例会形式]小组讨论 [例会地点]三号公寓楼会客厅 [例会主持]李孟 [会议记录]毛宇 会议整体流程 一. ...

  8. Daily Scrum02 11.30

    纵然编译大作业压顶,大家还是顶住压力,保证了软工项目的持续进行. Member Today's Task Tomorrow's Task 李孟 Task856 熟悉单元测试方法熟悉单元测试方法 Tas ...

  9. java多线程二之线程同步的三种方法

          java多线程的难点是在:处理多个线程同步与并发运行时线程间的通信问题.java在处理线程同步时,常用方法有: 1.synchronized关键字. 2.Lock显示加锁. 3.信号量Se ...

  10. Linux建立FTP服务器

    http://blog.chinaunix.net/uid-20541719-id-1931116.html http://www.cnblogs.com/hnrainll/archive/2011/ ...