传送门

思路

显然是树形DP,显然是斜率优化,唯一的问题就是该怎么维护凸包。

套路1:树上斜率优化,在没有这题的路程的限制的情况下,可以维护一个单调栈,每次加入点的时候二分它会加到哪里,然后替换并记录,等从这个点回溯上来的时候再撤销。

套路2:有路程限制时,不能简单替换,因为你可能会替换掉一个下面有用的点,然后WA掉。解决方法是用树状数组维护后缀单调栈,同样要支持撤销。

听着很简单,但代码不是很好写。

代码

第82行少打一个\(dep\)调了一下午,身败名裂……

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 202200
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__zz=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register ll x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__zz]=x%10+48,x/=10);
while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
}
void file()
{
#ifdef NTFOrz
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std; int n;
#define N (n+10)
struct hh{int t;ll w;int nxt;}edge[sz<<1];
int head[sz],ecnt;
void make_edge(int f,int t,ll w){edge[++ecnt]=(hh){t,w,head[f]};head[f]=ecnt;} ll dep[sz],dp[sz],P[sz],Q[sz],L[sz];
int a[sz],c;
#define Convex vector<int>
Convex tr[sz];int siz[sz];
ll Calc(int id,ll k)
{
if (!siz[id]) return 1e18;
int l=0,r=siz[id]-1;
while (233)
{
if (r-l<=10)
{
ll ret=1e18;
rep(i,l,r) chkmin(ret,dp[tr[id][i]]-k*dep[tr[id][i]]);
return ret;
}
int mid=(l+r)>>1;
if (dp[tr[id][mid]]-k*dep[tr[id][mid]]<dp[tr[id][mid+1]]-k*dep[tr[id][mid+1]]) r=mid;
else l=mid+1;
}
}
ll calc(int x,ll k){ll ret=1e18;while (x) chkmin(ret,Calc(x,k)),x-=(x&(-x));return ret;}
struct hhh{int x,y,siz;};
map<pii,hhh>M;
db K(int x,int y){return 1.0*(dp[y]-dp[x])/(dep[y]-dep[x]);}
void Insert(int id,int x)
{
int l=1,r=siz[id]-1,pos=(int)tr[id].size();
while (l<=r)
{
int p=(l+r)>>1;
if (dep[tr[id][p-1]]==dep[x])
{
if (dp[tr[id][p-1]]<=dp[x]) return;
else pos=p-1,r=p-2;
continue;
}
if (K(tr[id][p-1],x)<K(tr[id][p-1],tr[id][p])) pos=p,r=p-1;
else l=p+1;
}
if (siz[id]&&dep[tr[id][siz[id]-1]]==dep[x]&&dp[tr[id][siz[id]-1]]<=dp[x]) return;
if (pos==(int)tr[id].size())
{
if (pos==siz[id])
{
tr[id].push_back(x);
M[MP(x,id)]=(hhh){pos,-1,siz[id]};++siz[id];
return;
}
pos=siz[id];
}
M[MP(x,id)]=(hhh){pos,tr[id][pos],siz[id]};tr[id][pos]=x;siz[id]=pos+1;
}
void insert(int x,int p){while (p<=N) Insert(p,x),p+=(p&(-p));}
void Reset(int id,int x)
{
hhh s=M[MP(x,id)];
tr[id][s.x]=s.y;siz[id]=s.siz;
if (s.y==-1) tr[id].pop_back();
}
void reset(int x,int p){while (p<=N) Reset(p,x),p+=(p&(-p));}
void dfs(int x,int fa)
{
a[++c]=x;insert(x,N-c);
#define v edge[i].t
go(x) if (v!=fa)
{
dep[v]=dep[x]+edge[i].w;
int l=1,r=c,pos;
while (l<=r)
{
int mid=(l+r)>>1;
if (dep[v]-dep[a[mid]]<=L[v]) pos=mid,r=mid-1;
else l=mid+1;
}
dp[v]=calc(N-pos,P[v])+P[v]*dep[v]+Q[v];
dfs(v,x);
}
reset(x,N-c);--c;
} int main()
{
file();
int _;
read(n,_);
int x;ll y;
rep(i,2,n) read(x,y,P[i],Q[i],L[i]),make_edge(x,i,y);
dfs(1,0);
rep(i,2,n) print(dp[i]);Ot();
return 0;
}

洛谷P2305 [NOI2014]购票 [DP,树状数组]的更多相关文章

  1. [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?

    其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...

  2. 洛谷P3688/uoj#291. [ZJOI2017]树状数组

    传送门(uoj) 传送门(洛谷) 这里是题解以及我的卡常数历程 话说后面那几组数据莫不是lxl出的这么毒 首先不难发现这个东西把查询前缀和变成了查询后缀和,结果就是查了\([l-1,r-1]\)的区间 ...

  3. 洛谷P3368 【模板】树状数组 2

    P3368 [模板]树状数组 2 102通过 206提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 如题,已知一个数列,你需要进行下面两 ...

  4. 洛谷P3374 【模板】树状数组 1

    P3374 [模板]树状数组 1 140通过 232提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 题目描述有误 题目描述 如题,已知一个数列,你需要进行下面两 ...

  5. 洛谷 P3368 【模板】树状数组 2

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  6. 洛谷 P3374 【模板】树状数组 1

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  7. 树状数组模板(pascal) 洛谷P3374 【模板】树状数组1

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  8. 洛谷 P3368 【模板】树状数组 2(区间修改点查询)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  9. 洛谷 P3368 【模板】树状数组 2 题解

    P3368 [模板]树状数组 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 输入格式 第一行包含两个整数N.M,分别表示该数列数字的个 ...

随机推荐

  1. Go net/http,web server

    net/http 包实现 HTTP Server Go 中,实现一个最简单的 http server 非常容易,代码如下: package main import ( "fmt" ...

  2. Python基础初识

    一.安装 暂时没空写,预留 二.python基础初识 2.1 注释 当行注释:# 被注释内容 多行注释:'''被注释内容''',或者"""被注释内容"" ...

  3. iOS - UIWebView和WKWebView的比较和选择-作为H5容器的一些探究

    一.Native开发中为什么需要H5容器 Native开发原生应用是手机操作系统厂商(目前主要是苹果的iOS和google的Android)对外界提供的标准化的开发模式,他们对于native开发提供了 ...

  4. javscript函数的运用

    函数,一段能够自动完成某些功能的代码块,函数的出现,既解决了重复使用重一功能的需求,又可以避免代码的臃肿性. 使用函数有两个要求:必须调用后才可以执行;函数名不要和关键字以及系统函数相同; 函数主要有 ...

  5. vue使用阿里矢量图标

    官方注册注册 1.加入购物车 在阿里矢量图标库将想要的图标加入购物车,然后在购物车中将图标添加到项目:     2.下载 到我的项目中,将图标下载到本地     3.解压引入 在vue项目的asset ...

  6. Java 之 反射机制

    反射:框架设计的灵魂 框架:是一个可以供我们使用的半成品软件.可以在框架的基础上进行软件开发,简化编码. 反射:将类的各个组成部分封装为其他对象,这就是反射机制. 好处: 1. 可以在程序运行过程中, ...

  7. SVN上传本地项目到服务器

    1. 在服务器新建一个文件夹目录: 2. 将新建的目录在本地check out下来: 3. 将自己的项目拷贝到check out下来的文件夹下: 4. 右键点击svnàAdd,选择所有添加: 5. 右 ...

  8. 一语道破Java 11的ZGC为何如此高效

    GC是大部分现代语言内置的特性,Java 11 新加入的ZGC号称可以达到10ms 以下的 GC 停顿,本文作者对这一新功能进行了深入解析.同时还对还对这一新功能带来的其他可能性做了展望.ZGC是否可 ...

  9. SUSE Ceph RBD Mirror - Storage 6

    Ceph采用的是强一致性同步模型,所有副本都必须完成写操作才算一次写入成功,这就导致不能很好地支持跨域部署,因为如果副本在异地,网络延迟就会很大,拖垮整个集群的写性能.因此,Ceph集群很少有跨域部署 ...

  10. Oracle基础知识【1】

    目录: 1.Oracle创建库.表 2.Oracle数据怎删查改操作 3.Oracle数据约束条件 Oracle创建库.表: create user user05 identified by 1234 ...