BZOJ 3963: [WF2011]MachineWorks 斜率优化 + splay动态维护凸包
Description
Input
Output
化成一次函数形式:
$-D_{i}\times G_{j}+F_{i}=f_{j}-P_{j}+R_{j}-G_{j}D_{j}-G_{j}$
$x=G_{j}$,$y=f_{j}-P_{j}+R_{j}-G_{j}D_{j}-G_{j}$,$slope=-D_{j}$
可以用斜率优化来求解.
然而,$x$ 并不单调,所以要用平衡树来动态维护这个凸包
我选择了 $splay$
一定要特别注意横坐标相等的情况,一定特判是无限大还是无限小
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 300000
#define inf 10000000000000009
#define ll long long
using namespace std;
const long double eps = 1e-10;
int root;
int idxx[maxn];
struct Splaytree
{
#define get(x) (ch[f[x]][1]==x)
int cnt;
int ch[maxn][2],f[maxn];
long double X[maxn],Y[maxn],lk[maxn],rk[maxn];
// i 在前, j 在后
long double slope(int i,int j)
{
if(fabs(X[i]-X[j])<=eps) return Y[j]>Y[i] ? (long double)inf : (long double)-inf;
return (Y[i]-Y[j])/(X[i]-X[j]);
}
inline void rotate(int x)
{
int old=f[x],fold=f[old],which=get(x);
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=fold;
if(fold) ch[fold][ch[fold][1]==old]=x;
}
inline void splay(int x,int &tar)
{
int fa,u=f[tar];
for(;(fa=f[x])!=u;rotate(x))
if(f[fa]!=u)
rotate(get(fa)==get(x)?fa:x);
tar=x;
}
inline int getl(int x)
{
while(ch[x][0]) x=ch[x][0];
return x;
}
inline int getr(int x)
{
while(ch[x][1]) x=ch[x][1];
return x;
}
inline void insert(int &o,double x,double y,int last)
{
if(!o)
{
o=++cnt;
f[o]=last, X[o]=x,Y[o]=y;
return;
}
insert(ch[o][x-X[o]>eps], x, y, o);
}
inline int getans(int x,double k)
{
if(!x) return 0;
if(k<=lk[x]+eps&&k+eps>=rk[x]) return x;
if(lk[x]<k+eps) return getans(ch[x][0], k);
else return getans(ch[x][1], k);
}
inline void del(int x)
{
if(!ch[x][0])
{
int right=getl(ch[x][1]);
splay(right,ch[x][1]), root=right, f[root]=ch[x][1]=0;
lk[root]=inf; }
else if(!ch[x][1])
{
int left=getr(ch[x][0]);
splay(left,ch[x][0]), root=left, f[root]=ch[x][0]=0;
rk[root]=-inf;
}
else
{
int left=getr(ch[x][0]),right=getl(ch[x][1]);
splay(left,ch[x][0]), splay(right,ch[x][1]);
root=left, f[root]=0, ch[root][1]=right, f[right]=root;
rk[root]=lk[right]=slope(root,right);
}
}
// 平衡树上查询前驱
inline int pre(int x)
{
int cur=ch[x][0],re=0;
while(cur)
{
if(slope(cur,x)+eps>=rk[cur]) re=cur,cur=ch[cur][0];
else cur=ch[cur][1];
}
return re;
}
// 平衡树上查询后继
inline int nxt(int x)
{
int cur=ch[x][1],re=0;
while(cur)
{
if(slope(x,cur)<=lk[cur]+eps) re=cur,cur=ch[cur][1];
else cur=ch[cur][0];
}
return re;
}
inline void maintain(int x)
{
splay(x,root);
if(ch[root][0])
{
int left=pre(root);
if(left)
{
splay(left, ch[x][0]);
ch[left][1]=f[ch[left][1]]=0;
rk[left]=lk[x]=slope(left, x);
}
else lk[x]=-inf;
}
else lk[x]=inf;
if(ch[x][1])
{
int right=nxt(x);
if(right)
{
splay(right, ch[x][1]);
ch[right][0]=f[ch[right][0]]=0;
rk[x]=lk[right]=slope(x, right);
}
else rk[x]=inf;
}
else rk[x]=-inf;
if(lk[x]-rk[x]<=eps) del(x);
}
}splay;
int n;
ll d;
struct Node
{
ll P,D,G,R;
}t[maxn];
ll F[maxn];
bool cmp(Node i,Node j) { return i.D<j.D; }
inline void work()
{
root=splay.cnt=0;
int i,j=0;
for(i=1;i<=n;++i) scanf("%lld%lld%lld%lld",&t[i].D,&t[i].P,&t[i].R,&t[i].G);
t[++n].D=d+1;
t[n].P=t[n].R=t[n].G=0;
sort(t+1,t+1+n,cmp);
ll ret=F[0], re=0;
for(i=1;i<=n;++i)
{
F[i]=F[i-1];
if(root)
{
j=splay.getans(root, (long double)-1.00000*t[i].D);
j=idxx[j];
re=F[j]-t[j].P+t[j].R+t[j].G*(t[i].D-t[j].D-1LL);
F[i]=max(F[i-1],re);
}
ret=max(ret,F[i]);
if(i!=n&&F[i]>=t[i].P)
{
splay.insert(root, (long double)t[i].G, (long double)(F[i]-t[i].P+t[i].R-t[i].G*(t[i].D+1LL)),0);
idxx[splay.cnt]=i;
splay.maintain(splay.cnt);
}
}
printf("%lld\n",ret);
for(int i=0;i<=splay.cnt;++i) splay.ch[i][0]=splay.ch[i][1]=splay.f[i]=splay.lk[i]=splay.rk[i]=0;
root=splay.cnt=0;
}
int main()
{
for(int cas=1;;++cas)
{
scanf("%d%lld%lld",&n,&F[0],&d);
if(n==0&&F[0]==0&&d==0) break;
printf("Case %d: ",cas);
work();
}
return 0;
}
BZOJ 3963: [WF2011]MachineWorks 斜率优化 + splay动态维护凸包的更多相关文章
- HDU 3824/ BZOJ 3963 [WF2011]MachineWorks (斜率优化DP+CDQ分治维护凸包)
题面 BZOJ传送门(中文题面但是权限题) HDU传送门(英文题面) 分析 定义f[i]f[i]f[i]表示在iii时间(离散化之后)卖出手上的机器的最大收益.转移方程式比较好写f[i]=max{f[ ...
- BZOJ 1492: [NOI2007]货币兑换Cash 斜率优化 + splay动态维护凸包
Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...
- ●BZOJ 3963 [WF2011]MachineWorks
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3963 题解: 斜率优化DP,CDQ分治. 先按时间排序.(规定以下内容的第i台机器的卖出时间 ...
- BZOJ 3963: [WF2011]MachineWorks [CDQ分治 斜率优化DP]
传送门 当然了WF的题uva hdu上也有 你的公司获得了一个厂房N天的使用权和一笔启动资金,你打算在这N天里租借机器进行生产来获得收益.可以租借的机器有M台.每台机器有四个参数D,P,R,G.你可以 ...
- [BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 5907 Solved: 2377[Submit][Sta ...
- BZOJ_3963_[WF2011]MachineWorks_斜率优化+CDQ分治
BZOJ_3963_[WF2011]MachineWorks_斜率优化+CDQ分治 Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM) ...
- BZOJ 1767] [Ceoi2009] harbingers (斜率优化)
[BZOJ 1767] [Ceoi2009] harbingers (斜率优化) 题面 给定一颗树,树中每个结点有一个邮递员,每个邮递员要沿着唯一的路径走向capital(1号结点),每到一个城市他可 ...
- 【BZOJ】3963: [WF2011]MachineWorks
[题意]给定n台在时间di可以买入的机器,pi买入,可在任意时间ri卖出,买入和卖出之间的持有时间每天产生gi金钱,任意时间至多持有一台机器.给定初始钱数c和总天数T,求最大收益.n<=10^5 ...
随机推荐
- 从Android手机中取出已安装的app包,导出apk
从Android手机中取出已安装的app包,导出apk TAG:Android,提取,apk,adb,pm,root,导出apk 假设有这样一个场景,A君看到你手机上一个实用APP,想要安装到自己手机 ...
- axios 获取不到数据错误
1.问题: 打算学习下vue,但是vue-resource作者已经不更新了,并且大家都建议用axios来进行前后端交互,所以就从学习axios开始. 但是在使用 axios 的过程中,自己写的接口竟然 ...
- 分享:陆行鸟BGM合集
第39首是原版哦 https://pan.baidu.com/mbox/homepage?short=pMkAqhX
- 剑指offer(2):字符串
C语言中的字符串 C语言中字符串的存储方式和数组类似,都是连续定长的内存块.字符串数组以\0结尾,所以会比正常数组多一位,char str3[5] = "1234"; //此处赋值 ...
- SSM001/构建maven多模块项目
一.Idea构建maven多模块项目 1.创建maven项目--创建父模块 [1].File->New->Module... [2].点击next,填写:GroupId,ArtifactI ...
- [Python3] 012 元组:list,我们不一样!
目录 0. 元组的独白 1. 元组的创建 2. 元组的特性 (1) 概述 (2) 少废话,上例子 1) 索引 2) 分片 3) 序列运算 4) 成员检测 3. 元组的遍历 (1) 简单总结 (2) 少 ...
- JWT详解-(JSON Web Token教程)
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法. 一.跨域认证的问题 互联网服务离不开用户认证.一般流程是下面这样. 1.用户向服务器发送用户名和密 ...
- selenium 等待时间3种方式
强制等待 sleep() -- 最不建议用 缺点:sleep(10)网络不好的情况,到10秒就抛出异常网络很好,1秒钟就响应了,白白等待多9秒 隐式等待 -- 也不是很理想的方法implicitly_ ...
- 身为一个小白,看到一篇值得看的文章。讲述小白学习python的6个方法。
01. Python怎么学? Python虽然号称非常简单,功能强大!但是再简单,它也是一门编程语言,任何一个编程语言都会包含: 内功,心法和招式,内功心法就是指的算法,数据结构: 招式就是任何一 ...
- jQuery的加法运算,val()获取的结果相加变成了字符串连接。
加法运算 ?想必大家听到这都会不屑了,加法运算这是多么简单的运算.然而有的时候在jQuery也让人挺头疼的. 常规的是: var num1 = 123; var num2=123; var total ...