@description@

在这道题种你需要解决一个全世界人类从存在起就在面临的最深刻的问题--如何发大财。

你是一名零件交易市场的中介。你的工作是从零件生产公司那里买到零件,然后把它们卖给零件消费公司。

每个零件消费公司在截止日期前每天都会对一个零件有一个开放式的需求,以及它愿意买下零件的价格。另一方面,每个零件生产公司在开始日期及以后都可以销售零件,以及它销售零件的价格。基于公平竞争法,你只能与一家生产公司、一家消费公司签订合同。

你可以在生产公司开始销售后每天从生产公司买一个零件,当然这也要在消费公司结束需求之前。

在这些天里,每天你可以从买卖差价中获取利润。你的任务是选择能使你利益最大化的生产公司与消费公司。

1≤m,n≤500 000

原题戳这里0.0

@solution@

实际上就是求 max{(qj - pi)*(ej - di) | ej > di}。

将 (qj, ej) 与 (pi, di) 都看成二维平面中的点,则相当于求以 (qj, ej) 为右上角,(pi, di) 为左下角的最大矩形面积。

注意到当 qk <= qj 且 ek <= ej 时,(qj, ej) 比 (qk, ek) 更容易合法且在更优,此时 k 就没有用了。

同理,当 pi <= pk 且 di <= dk 时,(pi, di) 比 (pk, dk) 一定更好。

所以最终两个序列的有用点一定是横坐标单增的同时纵坐标单减。

不会做了。于是考虑决策单调性。手推了一下式子发现的确有决策单调性(这里就不推了,挺好推的)。

然而。。。如果仅仅这样就结束了我才不会写这篇博客作为教训。。。

注意到每个点 (qj, ej) 的决策是有范围:对应的 i 要满足 pi < qj, di < ej。否则决策单调性的式子就推不出来了(?应该是吧,因为有点久了所以不是很确定)。

而这些 i 构成了一个区间 [le(j), ri(j)],其中 le(j) 的纵坐标 < ej 且最小,ri(j) 的横坐标 < pi 且最大。

而假如你像我一样采用分治法,那么就会遇到一个问题:有可能当前分治的决策点区间 [opl, opr] 与我们 mid 的决策范围没有交集。。。

而这又有几种情况:一种是 le(mid) > ri(mid),即 mid 本身没有决策的点。此时分治 [opl, ri(mid)] 与 [le(mid), opr],可以保证时间复杂度与正确性。

另外两种其实是类似的,一种是 le(mid) > opr,此时把 [opl, opr] 传给 [l, mid-1] 即可;还有一种是 ri(mid) < opl,反过来传给右边的 [mid, r] 即可。

@accepted code@

#include <cstdio>
#include <algorithm>
using namespace std; const int MAXN = 500000; typedef long long ll; struct node{
int x, y;
node(int _x=0, int _y=0) : x(_x), y(_y) {}
friend bool operator < (node a, node b) {
return (a.x == b.x) ? a.y < b.y : a.x < b.x;
}
}t[MAXN + 5], a[MAXN + 5], b[MAXN + 5];
ll ans;
int le[MAXN + 5], ri[MAXN + 5];
void solve(int opl, int opr, int l, int r) {
if( l > r ) return ;
int m = (l + r) >> 1, opm = opl;
if( ri[m] < opl ) solve(opl, opr, m + 1, r);
else if( le[m] > opr ) solve(opl, opr, l, m - 1);
else if( le[m] > ri[m] ) {
solve(opl, ri[m], l, m - 1);
solve(le[m], opr, m + 1, r);
}
else {
ll res = -1;
for(int i=opl;i<=opr;i++) {
ll t = 1LL*(b[m].x - a[i].x)*(b[m].y - a[i].y);
if( b[m].x >= a[i].x && b[m].y >= a[i].y && t >= res )
opm = i, res = t;
}
ans = max(ans, res);
solve(opl, opm, l, m - 1);
solve(opm, opr, m + 1, r);
}
}
int m, n, ca, cb;
int main() {
scanf("%d%d", &m, &n);
for(int i=1;i<=m;i++) {
int p, d; scanf("%d%d", &p, &d);
t[i] = node(p, d);
}
sort(t + 1, t + m + 1);
for(int i=1;i<=m;i++) {
if( !ca || !(t[i].x >= a[ca].x && t[i].y >= a[ca].y) )
a[++ca] = t[i];
}
for(int i=1;i<=n;i++) {
int q, e; scanf("%d%d", &q, &e);
t[i] = node(q, e);
}
sort(t + 1, t + n + 1);
for(int i=1;i<=n;i++) {
while( cb && t[i].x >= b[cb].x && t[i].y >= b[cb].y )
cb--;
b[++cb] = t[i];
}
le[0] = 1, ri[0] = 0;
for(int i=1;i<=n;i++) {
le[i] = le[i-1], ri[i] = ri[i-1];
while( le[i] <= m && a[le[i]].y > b[i].y ) le[i]++;
while( ri[i] < m && a[ri[i]+1].x <= b[i].x )
ri[i]++;
}
solve(1, ca, 1, cb);
printf("%lld\n", ans);
}

@details@

比较详细的细节都在 solution 里面说啦。

@bzoj - 4951@ [Wf2017]Money for Nothing的更多相关文章

  1. bzoj 4951: [Wf2017]Money for Nothing【分治】

    参考:https://blog.csdn.net/herobrine_tkj/article/details/78404426?locationNum=8&fps=1 为什么从1开始存就挂了, ...

  2. BZOJ 4951 [WF2017]Money for Nothing (决策单调优化DP+分治)

    题目大意:略 题目传送门 不愧是$World final$的神题,代码短,思维强度大,细节多到吐..调了足足2h 贪心 我们利用贪心的思想,发现有一些工厂/公司是非常黑心的 以工厂为例,对于一个工厂$ ...

  3. 4951: [Wf2017]Money for Nothing 决策单调性 分治

    Bzoj4951:决策单调性 分治 国际惯例题面:一句话题面:供应商出货日期为Ei,售价为Pi:用户收购截止日期为Si,收购价格为Gi.我们要求max((Si-Ej)*(Gi-Pj)).显然如果我们把 ...

  4. 【刷题】BZOJ 4950 [Wf2017]Mission Improbable

    Description 那是春日里一个天气晴朗的好日子,你准备去见见你的老朋友Patrick,也是你之前的犯罪同伙.Patrick在编程竞赛上豪赌输掉了一大笔钱,所以他需要再干一票.为此他需要你的帮助 ...

  5. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  8. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. PAT甲级——A1055 The World's Richest

    Forbes magazine publishes every year its list of billionaires based on the annual ranking of the wor ...

  2. windows2008解决必须使用角色管理工具安装或配置 NET3.5 sp1问题

    win2008系统安装网站环境系统的时候常常提示:必须使用角色管理工具 安装或配置microsoft.net framework 3.5 sp1 ,导致安装不成功. 原因在于windows2008系统 ...

  3. JSP页面格式化timestamp时间

    timestamp类型返回并直接取值显示会带小尾巴 偶然发现 <fmt:formatDate value="${order.createTime}" type="b ...

  4. 使用Maven编译运行Storm入门代码(Storm starter)(转)

    Storm 官方提供了入门代码(Storm starter),即 Storm安装教程 中所运行的实例(storm-starter-topologies-0.9.6.jar),该入门代码位于 /usr/ ...

  5. sudo 授权许可使用的su,也是受限制的su

    sudo 的适用条件: 由于su 对切换到超级权限用户root后,权限的无限制性,所以su并不能担任多个管理员所管理的系统.如果用su 来切换到超级用户来管理系统,也不能明确哪些工作是由哪个管理员进行 ...

  6. workbench使用

    1.你是指默认的mysql目录下data里面的'mysql'这个schema没有在workbench里面看到吧?点击菜单-Edit->Preferences里面的SQL Editor,然后把&q ...

  7. PYTHON__ ITERTOOLS模块

    组成 总体,整体了解 无限迭代器 迭代器 参数 结果 例子 count() start, [step] start, start+step, start+2*step, ... count(10) - ...

  8. angular依赖注入(1)——从父元素到子元素的数据注入

    1.什么是依赖注入? 依赖注入是一种编程模式,可以让类从外部源中获得它的依赖,不必亲自创建他们. (这就达到了一个效果,我不知道我是怎么实现的,但我创建了一个实现他的接口,然后接口封装起来,1.可以分 ...

  9. c#多线程通信之委托(事件)

    在研究c# 线程之间通信时,发现传统的方法大概有三种 ①全局变量,由于同一进程下的多个进程之间共享数据空间,所以使用全局变量是最简单的方法,但要记住使用volatile进行限制. ②线程之间发送消息( ...

  10. netbeans调试webapp 只能用localhost访问

    etbeans 我的电脑是192.168.0.2,用这个地址访问 网上有人说,分两种情况 此问题分两种情况: 1. 可以用127.0.0.1访问 2. 不能用127.0.0.1访问 针对第一种情况,我 ...