其他分享
首页 > 其他分享> > Luogu3994 高速公路

Luogu3994 高速公路

作者:互联网

Description

link

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