[Noi2014]购票 斜率优化DP+可持久化凸包
貌似网上大部分题解都是CDQ分治+点分治然后再斜率优化DP,我貌似并没有用这个方法。
这一题跟这题有点像,只不过多了一个l的限制
如果说直接跑斜率优化DP,存储整个序列的话,显然是不行的,如图所示(图鸣谢某巨佬)

所以我们需要种一棵线段树,每个线段树内存储一个存当前区间凸包的单调栈,弹出插入操作跟刚刚说的那题一样。
查询的话就查询下整个区间中所有凸包上的最大值就可以了。
时间复杂度:$O(n\log^2\ n)$。写起来并不算很困难。
#include<bits/stdc++.h>
#define M 200005
#define L long long
#define INF (1LL<<62)
using namespace std; struct edge{int u,v,next;}e[M]={}; int head[M]={},use=;
void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
L D[M]={},P[M]={},Q[M]={},F[M]={},n,t,up[M]={};
double slope(int i,int j){return .*(F[i]-F[j])/(D[i]-D[j]);}
L getans(int x,int y){if(y==) return INF; return F[y]+(D[x]-D[y])*P[x]+Q[x];} int f[M][]={},dep[M]={};
int jump(int x,L dis){
for(int i=;~i;i--)
if(D[x]-D[f[x][i]]<=dis){
dis-=D[x]-D[f[x][i]];
x=f[x][i];
}
return max(,dep[x]);
} struct tb{
int *q,l,r;
tb(){l=; r=; q=NULL;}
tb(int len){
q=new int[len+];
memset(q,,sizeof(int )*(len+));
l=; r=;
}
int add(int x){
int ll=l,rr=r-;
if(l<r){
while(ll<rr){
int mid=(ll+rr)>>;
if(slope(q[mid],q[mid+])>slope(q[mid+],x)) rr=mid;
else ll=mid+;
}
if(slope(q[ll],q[ll+])<slope(q[ll+],x)) ll++;
r=ll;
}
int res=q[++r]; q[r]=x;
return res;
}
L getans(int x){
int ll=l,rr=r-;
if(l>=r) return q[l];
while(ll<rr){
int mid=(ll+rr+)>>;
if(slope(q[mid],q[mid+])<P[x]) ll=mid;
else rr=mid-;
}
if(slope(q[ll],q[ll+])<P[x])
return q[ll+];
return q[ll];
}
}; struct node{int l,r;tb a;}a[M*];
void build(int x,int l,int r){
a[x].l=l; a[x].r=r;
a[x].a=tb(r-l+);
if(l==r) return; int mid=(l+r)>>;
build(x<<,l,mid); build(x<<|,mid+,r);
}
void updata(int x,int k,int id,int lastL[],int lastR[],int lastT[]){
lastL[]=a[x].a.l; lastR[]=a[x].a.r;
lastT[]=a[x].a.add(id);
if(a[x].l==a[x].r) return; int mid=(a[x].l+a[x].r)>>;
if(k<=mid) updata(x<<,k,id,lastL+,lastR+,lastT+);
else updata(x<<|,k,id,lastL+,lastR+,lastT+);
}
void reset(int x,int k,int lastL[],int lastR[],int lastT[]){
a[x].a.q[a[x].a.r]=lastT[];
a[x].a.l=lastL[]; a[x].a.r=lastR[];
if(a[x].l==a[x].r) return; int mid=(a[x].l+a[x].r)>>;
if(k<=mid) reset(x<<,k,lastL+,lastR+,lastT+);
else reset(x<<|,k,lastL+,lastR+,lastT+);
}
L query(int x,int l,int r,int k){
if(l<=a[x].l&&a[x].r<=r)
return getans(k,a[x].a.getans(k));
L mid=(a[x].l+a[x].r)>>,minn=INF;
if(l<=mid) minn=min(minn,query(x<<,l,r,k));
if(mid<r) minn=min(minn,query(x<<|,l,r,k));
return minn;
} void dfs(int x,int fa,L Dis){
f[x][]=fa; dep[x]=dep[fa]+; D[x]=Dis;
for(int i=;i<;i++) f[x][i]=f[f[x][i-]][i-];
int y=jump(x,up[x]);
F[x]=query(,y,dep[x],x);
int lastL[]={},lastR[]={},lastT[]={};
updata(,dep[x],x,lastL,lastR,lastT);
for(int i=head[x];i;i=e[i].next) dfs(e[i].u,x,Dis+e[i].v);
reset(,dep[x],lastL,lastR,lastT);
}
int main(){
scanf("%d%d",&n,&t);
for(int i=;i<=n;i++){
L fa,dis; scanf("%lld%lld%lld%lld%lld",&fa,&dis,P+i,Q+i,up+i);
add(fa,i,dis);
}
build(,,n);
int hh[]; updata(,,,hh,hh,hh);
dep[]=; D[]=-INF;
for(int i=head[];i;i=e[i].next) dfs(e[i].u,,e[i].v);
for(int i=;i<=n;i++) printf("%lld\n",F[i]);
}
[Noi2014]购票 斜率优化DP+可持久化凸包的更多相关文章
- 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治
题目描述 给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费 ...
- [NOI2014]购票 --- 斜率优化 + 树形DP + 数据结构
[NOI2014]购票 题目描述 今年夏天,NOI在SZ市迎来了她30周岁的生日. 来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每 ...
- [NOI2014]购票(斜率优化+线段树)
题目描述 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的父亲用道路连接 ...
- [BZOJ3672][Noi2014]购票 斜率优化+点分治+cdq分治
3672: [Noi2014]购票 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1749 Solved: 885[Submit][Status][ ...
- [NOI2014]购票——斜率优化+树链剖分+线段树
建议到UOJ上去交 题解 一眼\(DP\),先把转移方程写出来 设\(dp[i]\)为从点\(i\)出发到点\(1\)的最小费用,那么存在转移 \[f[i]=min\{f[j]+(d[i]-d[j]) ...
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...
- 斜率优化DP学习笔记
先摆上学习的文章: orzzz:斜率优化dp学习 Accept:斜率优化DP 感谢dalao们的讲解,还是十分清晰的 斜率优化$DP$的本质是,通过转移的一些性质,避免枚举地得到最优转移 经典题:HD ...
- 【学习笔记】动态规划—斜率优化DP(超详细)
[学习笔记]动态规划-斜率优化DP(超详细) [前言] 第一次写这么长的文章. 写完后感觉对斜优的理解又加深了一些. 斜优通常与决策单调性同时出现.可以说决策单调性是斜率优化的前提. 斜率优化 \(D ...
- HDU3507 Print Article(斜率优化dp)
前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs. ...
随机推荐
- 卡特尔16PF性格测试与答案
大学生在职业生涯规划时,必须充分注意到自己的性格和职业的适宜性.性格是指一个人在生活中形成的对现实的稳定的态度和行为方式.研究表明,性格影响着一个人的职业取向,由于性格的不同,每个人对工作和职业的态度 ...
- nginx集群tomcat,session共享问题
tomcat-redis-session-manager版本: apache-tomcat-8.0.32.nginx-1.13.12.redis_3.2.1 github地址: https://git ...
- 动词的时态(Les temps du verbe )
在开始讲解直陈式现在时的主要用法之前,我们有必要先搞清楚两个基本概念:▶语式(mode):语式是动词表达动作的方式.一个动作,可以作为实在的事表达出来,也可以作为希望或单纯设想的事表达出来,法语动词共 ...
- python面向对象-1方法、构造函数
类是指:描述一种事物的定义,是个抽象的概念 实例指:该种事物的一个具体的个体,是具体的东西 打个比方: “人”是一个类.“张三”是人类的一个具体例子 在编程时也是同样的道理,你先自己定义一个“类”,当 ...
- Vivado 常见报错
1.[Synth 8-2543] port connections cannot be mixed ordered and named 说明例化时最后一个信号添加了一个逗号. 2. 原因:报告说明有一 ...
- 仿iPhone滑屏操作
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <m ...
- (最短路 dijkstra)昂贵的聘礼 -- poj -- 1062
链接: http://poj.org/problem?id=1062 昂贵的聘礼 Time Limit: 1000MS Memory Limit: 10000K Total Submissions ...
- C++ sort()函数的用法
C++sort()函数的用法 C++sort()函数的用法 近来看了c++标准库这本书,学到了很多,就把这其中的一点C++sort()函数的用法写下来和大家分享吧! (一)为什么要用c++标准库里的排 ...
- hdu 5067 遍历指定点集最小时间
http://acm.hdu.edu.cn/showproblem.php?pid=5067 贴题解 由于Harry的dig machine是无限大的,而装载石头和卸载石头是不费时间的,所以问题可以转 ...
- redis开机自启动脚本(linux)
目前redis放在home下的文件夹中,写一个脚本,待系统启动的过程中,去启动该脚本. 脚本:redis.sh #!/bin/sh /home/juepei/Downloads/redis-3.0.0 ...