[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. ...
随机推荐
- c++ => new/delete
new的具体使用方式如下: 类型 *变量名 = new 类型; delete 变量 / delete[] 变量; 类型包括数组.结构体和类 数组申请动态内存后,要使用delete[]才能把内存清除干净 ...
- Git在windows环境下的使用教程
前言 安装 配置 关于git使用的几个问题 后记 关于代码托管,以前用过vss和svn,看博客或论坛的时候,经常有人提到github,有很多著名的开源软件都托管在github,想来肯定不错(莫笑),当 ...
- 20145234黄斐《java程序设计》第六周
教材学习内容总结 第十章:输入与输出 InputStream与OutputStream 流(Stream)是对「输入输出」的抽象,注意「输入输出」是相对程序而言的 InputStream与Output ...
- PAT甲 1008. Elevator (20) 2016-09-09 23:00 22人阅读 评论(0) 收藏
1008. Elevator (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The highest ...
- oracle中row_number() over()分析函数用法
row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内 ...
- Paul Simon -- Duncan
Paul Simon -- Duncan (London,January 1972) Couple in the next roomBound to win a prizeTheyve been go ...
- Redis Sentinel基本介绍(翻译以及总结)
目录 Redis Sentinel介绍 分布式的Redis Sentinel 快速开始 获取Sentinel 启动Sentinel 部署Sentinel的基本要求 配置Sentinel 其他的Sent ...
- Sql 辅助
1.清空数据表 SELECT 'TRUNCATE TABLE '+name AS TruncateSql FROM sys.tables
- 如何连接MSSQLSERVER2014(其他版本数据库大体相同)
购买了服务器后我在上面安装了SqlServer2014,但是程序中总是远程连接不上,特此记录一下: 一.一些基本设置如下链接: 转载自:https://blog.sun0816.com/20381.h ...
- SqlServer数据库同时备份到两台服务器上(并自动删除过期文件)
数据库同时备份到两台服务器上(并自动删除过期文件) 举例 :(本地)服务器A: IP :192.168.1.1 (远程)服务器B: IP :192.168.1.2 数据库版本:SqlServer200 ...