Luogu3994 高速公路
作者:互联网
Description
Solution
方程显然吧
\[f_i=\min\limits_{j\in \{anc_i\}} f_j+p_i\times(dep_i-dep_j)+q_i \]
然后斜率优化
以上都是比较基础的部分
然后我们主要考虑怎么在斜率优化的时候进行对于单调队列的处理
观察到我们这个题一个单链上的修改可能对于其他链有影响
所以一般性的做法显然不成
再观察
我们都会修改啥呢?
弹栈,进栈,和添加一个值对吧
那么我们记录下来然后还原不就 \(OK\) 了
这里转移的时候要二分决策点来保证复杂度
不二分也能过??【哭】
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=1e6+10;
struct node{
int to,dis,nxt;
}e[N<<1];
int head[N],cnt,n,dep[N],q[N],p[N],Q[N],f[N],h,t;
inline void add(int u,int v,int w)
{
e[++cnt].dis=w; e[cnt].nxt=head[u]; e[cnt].to=v;
return head[u]=cnt,void();
}
inline void dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt) dep[e[i].to]=dep[x]+e[i].dis,dfs(e[i].to);
return ;
}
inline double slope(int x,int y)
{
return 1.0*(f[x]-f[y])/(dep[x]-dep[y]);
}
inline void work(int x)
{
int th=h,tt=t;
int l=h,r=t-1,res=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(slope(Q[mid],Q[mid+1])>=p[x]) res=mid,r=mid-1;
else l=mid+1;
} if(res!=-1) h=res; else h=t;
f[x]=f[Q[h]]+(dep[x]-dep[Q[h]])*p[x]+q[x];
l=h; r=t-1; res=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(slope(Q[mid],Q[mid+1])<slope(Q[mid+1],x)) res=mid,l=mid+1;
else r=mid-1;
}if(res!=-1) t=res+1; else t=h;
int tv=Q[++t]; Q[t]=x;
for(int i=head[x];i;i=e[i].nxt) work(e[i].to);
h=th; Q[t]=tv; t=tt;
return ;
}
signed main()
{
n=read();
for(int i=2;i<=n;++i)
{
int fa=read(),dis=read();
p[i]=read(); q[i]=read();
add(fa,i,dis);
} dfs(1);
for(int i=head[1];i;i=e[i].nxt) Q[h=t=1]=1,work(e[i].to);
for(int i=2;i<=n;++i) printf("%lld\n",f[i]);
return 0;
}
}
signed main(){return yspm::main();}
Review
这种还原的思想还是很值得学习的
最后一句闲话:可持久化数组好!!
标签:slope,dep,res,mid,高速公路,int,while,Luogu3994 来源: https://www.cnblogs.com/yspm/p/12898899.html