李超线段树wa on 6
查看原帖
李超线段树wa on 6
718722
adjective楼主2023/10/18 17:14
#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N=200005,L=-1e5,R=1e5,INF=0x3f3f3f3f;

int n,a1[N],b1[N],deg[N],f[N];//deg为点的度数 f为答案 

int ne[N*2],head[N],v[N*2],tote=1;
void adde(int x,int y){ne[++tote]=head[x];head[x]=tote;v[tote]=y;}

int rt[N];
struct EDGE{int k,b;}e[N];//k==b[i]
struct TREE{int l,r,d;}tr[N<<5];int cnt=0;

int sol(int x,int i){if(!i) return INF;else return e[i].k*x+e[i].b;}
//李超线段树 
void add(int &id,int l,int r,int v){
	if(!id) id=++cnt;
	int m=(l+r)/2,d=tr[id].d;
	int m1=sol(m,v),m2=sol(m,d);
	if(m1<m2) swap(v,tr[id].d);
	d=tr[id].d;
	int l1=sol(l,d),l2=sol(l,v);
	int r1=sol(r,d),r2=sol(r,v);
	if(l2>=l1&&r2>=r1) return;
	if(l2<l1) add(tr[id].l,l,m,v);
	else add(tr[id].r,m+1,r,v);
}

void ask(int id,int l,int r,int s,int u){
	if(!id) return;
	int m=(l+r)/2;
	f[u]=min(f[u],sol(s,tr[id].d));
	if(s<=m) ask(tr[id].l,l,m,s,u);
	else ask(tr[id].r,m+1,r,s,u);
}
//合并 
int merge(int a,int b,int l,int r){
	if(!a||!b) return a^b;
	int m=(l+r)/2;
	add(a,l,r,tr[b].d);
	tr[a].l=merge(tr[a].l,tr[b].l,l,m);
	tr[a].r=merge(tr[a].r,tr[b].r,m+1,r);
	return a;
}

void dfs(int u,int fu){
	for(int i=head[u];i;i=ne[i]){
		if(v[i]==fu) continue;
		dfs(v[i],u);
		rt[u]=merge(rt[u],rt[v[i]],L,R);
	}
	if(f[u]==INF) ask(rt[u],L,R,a1[u],u);
	e[u]=(EDGE){b1[u],f[u]};
	add(rt[u],L,R,u);
}

signed main(){
	scanf("%lld", &n);
	for(int i=1;i<=n;i++) scanf("%lld", &a1[i]);
	for(int i=1;i<=n;i++) scanf("%lld", &b1[i]);
	for(int i=1;i<n;i++){int x,y;scanf("%lld %lld", &x, &y);adde(x,y);adde(y,x);deg[x]++;deg[y]++;}
	for(int i=1;i<=n;i++) if(deg[i]==1&&i!=1) f[i]=0;else f[i]=INF;
	
	dfs(1,0);
	for(int i=1;i<=n;i++) printf("%lld ", f[i]);
	return 0;
}
2023/10/18 17:14
加载中...