zoukankan      html  css  js  c++  java
  • Luogu3994 高速公路

    Description

    link

    Solution

    方程显然吧

    [f_i=minlimits_{jin {anc_i}} f_j+p_i imes(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
    ",f[i]);
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    

    Review

    这种还原的思想还是很值得学习的

    最后一句闲话:可持久化数组好!!

  • 相关阅读:
    OC
    OC
    OC
    OC
    OC
    Oracle wm_concat()函数
    字符串拼接
    easyui扩展数据表格点击加号拓展
    子tab里面新增tab(top.jQuery)
    combox datagrid重复请求问题
  • 原文地址:https://www.cnblogs.com/yspm/p/12898899.html
Copyright © 2011-2022 走看看