首页 > 其他分享 >CF932F Escape Through Leaf

CF932F Escape Through Leaf

时间:2022-10-06 15:22:21浏览次数:33  
标签:ch Leaf int mid num Through put calc CF932F

CF932F Escape Through Leaf

设 \(f_x\) 表示点 \(x\) 到叶子节点的最优答案。

考虑 \(x\) 下一步跳到点 \(y\),可以得到转移方程为

\[f_x=\min_{y\in son_x} f_y+a_x\times b_y \]

将 \(f_y\) 看作 \(b\),将 \(a_x\) 看作 \(x\),将 \(b_y\) 看作 \(k\),则式子的右边为多条直线,而要求的答案是直线在 \(x=a_x\) 处最小值。

考虑使用李超线段树维护直线的下凸壳(因为求的是 \(\min\)),对于一个节点 \(x\),先从子节点中转移当前点的 \(f_x\),再将子节点全部合并并插入当前节点的直线。

#include<bits/stdc++.h>
using namespace std;
namespace IO{
	template<typename T>inline bool read(T &x){
		x=0;
		char ch=getchar();
		bool flag=0,ret=0;
		while(ch<'0'||ch>'9') flag=flag||(ch=='-'),ch=getchar();
		while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(),ret=1;
		x=flag?-x:x;
        return ret;
	}
	template<typename T,typename ...Args>inline bool read(T& a,Args& ...args){
	    return read(a)&&read(args...);
	}
	template<typename T>void prt(T x){
		if(x>9) prt(x/10);
		putchar(x%10+'0');
	}
	template<typename T>inline void put(T x){
		if(x<0) putchar('-'),x=-x;
		prt(x);
	}
	template<typename T>inline void put(char ch,T x){
		if(x<0) putchar('-'),x=-x;
		prt(x);
		putchar(ch);
	}
	template<typename T,typename ...Args>inline void put(T a,Args ...args){
	    put(a);
		put(args...);
	}
	template<typename T,typename ...Args>inline void put(const char ch,T a,Args ...args){
	    put(ch,a);
		put(ch,args...);
	}
	inline void put(string s){
		for(int i=0,sz=s.length();i<sz;i++) putchar(s[i]);
	}
	inline void put(const char* s){
		for(int i=0,sz=strlen(s);i<sz;i++) putchar(s[i]);
	}
}
using namespace IO;
#define N 200005
#define Dt 100005
#define Maxn 200010
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
int n,head[N],cnt,idx;
ll ans[N],a[N],b[N];
struct line{
	ll k,b;
}l[N];
inline ll calc(int id,int x){
	return l[id].k*x+l[id].b;
}
struct edge{
	int v,nxt;
}e[N<<1];
inline void add(int u,int v){
	e[++cnt]=(edge){v,head[u]},head[u]=cnt;
}
int rt[N*25];
struct node{
	int s,ls,rs;
}t[N*25];
#define lc(x) t[x].ls
#define rc(x) t[x].rs
#define s(x) t[x].s
inline void update(int &x,int l,int r,int num){
	if(!x) return x=++idx,s(x)=num,void();
	int mid=l+r>>1;
	if(calc(s(x),mid)>calc(num,mid)) swap(s(x),num);
	if(calc(s(x),l)>calc(num,l)) update(lc(x),l,mid,num);
	if(calc(s(x),r)>calc(num,r)) update(rc(x),mid+1,r,num);	
}
inline ll query(int &x,int l,int r,int num){
	if(!x) return inf;
	int mid=l+r>>1;
	ll res=calc(s(x),num);
	if(num<=mid) res=min(res,query(lc(x),l,mid,num));
	else res=min(res,query(rc(x),mid+1,r,num));
	return res;
}
inline int merge(int x,int y,int l,int r){
	if(!x||!y) return x|y;
	int mid=l+r>>1;
	update(x,l,r,s(y));//把y的信息插入x
	lc(x)=merge(lc(x),lc(y),l,mid);
	rc(x)=merge(rc(x),rc(y),mid+1,r);
	return x; 
}
inline void dfs(int x,int fa){
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].v;
		if(v==fa) continue;
		dfs(v,x);
		rt[x]=merge(rt[x],rt[v],1,Maxn);
	}
	ans[x]=query(rt[x],1,Maxn,a[x]+Dt);
	if(ans[x]==inf) ans[x]=0;
	l[x]=(line){b[x],ans[x]-b[x]*Dt};
	update(rt[x],1,Maxn,x);
}
int main(){
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	for(int i=1;i<=n;i++) read(b[i]);
	for(int i=1,u,v;i<n;i++) read(u,v),add(u,v),add(v,u);
	dfs(1,0);
	for(int i=1;i<=n;i++) put(' ',ans[i]);
	return 0;
}

标签:ch,Leaf,int,mid,num,Through,put,calc,CF932F
From: https://www.cnblogs.com/fzj2007/p/16757683.html

相关文章