F. Escape Through Leaf
time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a tree with n nodes (numbered from 1 to n) rooted at node 1. Also, each node has two values associated with it. The values for i-th node are ai and bi.

You can jump from a node to any node in its subtree. The cost of one jump from node x to node y is the product of ax and by. The total cost of a path formed by one or more jumps is sum of costs of individual jumps. For every node, calculate the minimum total cost to reach any leaf from that node. Pay attention, that root can never be leaf, even if it has degree 1.

Note that you cannot jump from a node to itself.

Input

The first line of input contains an integer n (2 ≤ n ≤ 10^5) — the number of nodes in the tree.

The second line contains n space-separated integers a1,  a2,  ...,  an( - 10^5  ≤  ai  ≤  10^5).

The third line contains n space-separated integers b1,  b2,  ...,  bn( - 10^5  ≤  bi  ≤  10^5).

Next n  -  1 lines contains two space-separated integers ui and vi (1 ≤ ui,  vi ≤  n) describing edge between nodes ui and vi in the tree.

Output

Output n space-separated integers, i-th of which denotes the minimum cost of a path from node i to reach any leaf.

Examples
input

Copy
3
2 10 -1
7 -7 5
2 3
2 1
output
10 50 0 
input

Copy
4
5 -10 5 7
-8 -80 -3 -10
2 1
2 4
1 3
output
-300 100 0 0 
Note

In the first example, node 3 is already a leaf, so the cost is 0. For node 2, jump to node 3 with cost a2 × b3 = 50. For node 1, jump directly to node 3 with cost a1 × b3 = 10.

In the second example, node 3 and node 4 are leaves, so the cost is 0. For node 2, jump to node 4 with cost a2 × b4 = 100. For node 1, jump to node 2 with cost a1 × b2 =  - 400 followed by a jump from 2 to 4 with cost a2 × b4 = 100.

题目大意:每个点有两个点权a,b,一个点i可以向它子树的任意一个点j中跳去,代价为ai * bj.求出每个点跳到任意一个叶子节点的最小代价.

分析:这道题还是比较难的.

   先考虑一个dp: f[i] = min{f[j] + a[i] * b[j]}. 复杂度是O(n^2),过不了,需要进行优化.

   观察这个式子,它长得特别像斜率优化一般式子,所以能不能考虑斜率优化呢? 显然也是不行的吧,这是在子树上操作,并不是在序列上操作.

   斜率优化虽然不行,但是可以借鉴它的思想:将b[j]当作斜率,f[j]当作截距. 对于每一个j,都有一条对应的直线. 那么题目就变成了在每个点i的子树中的点j表示的直线中,找到一条,使得f[j] + a[i] * b[j]最大. 这个可以利用线段树标记永久化来解决.   

   现在最棘手的一个问题就是:怎么样才能使得线段树只记录当前点的子树的信息呢?

   可以用dsu on tree! 使用dsu on tree的条件是没有修改操作,并且只涉及到子树内的查询. 恰好满足.  但是dsu on tree会有一个清楚答案的过程,怎么把一个线段树上记录的信息给清除呢? 动态加点即可,这就相当于又重建了一棵线段树.

   挺好的一道题,将斜率优化的思想,标记永久化,dsu on tree都给考了一遍. 能够运用这些方法的题目的特征要记清楚!

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
const ll maxn = ,inf = (1LL<<),maxx = ;
ll n,a[maxn],b[maxn],K[maxn << ],B[maxn << ],ans[maxn],cnt,root,tr[maxn << ];
ll head[maxn],to[maxn * ],nextt[maxn * ],tot = ,sizee[maxn],son[maxn],lson[maxn << ],rson[maxn << ]; void add(ll x,ll y)
{
to[tot] = y;
nextt[tot] = head[x];
head[x] = tot++;
} void dfs(ll u,ll fa)
{
sizee[u] = ;
for (ll i = head[u];i;i = nextt[i])
{
ll v = to[i];
if (v == fa)
continue;
dfs(v,u);
sizee[u] += sizee[v];
if (sizee[v] > sizee[son[u]])
son[u] = v;
}
} double jiao(ll x,ll y)
{
return (double)(B[x] - B[y]) / (K[y] - K[x]);
} void insert(ll &tott,ll l,ll r,ll v)
{
if (!tott)
{
tott = ++cnt;
lson[tott] = rson[tott] = ;
tr[tott] = v;
return;
}
ll mid = (l + r) >> ;
ll l1 = B[v] + K[v] * l,l2 = B[v] + K[v] * r;
ll r1 = B[tr[tott]] + K[tr[tott]] * l,r2 = B[tr[tott]] + K[tr[tott]] * r;
if (l1 >= r1 && l2 >= r2)
return;
if (l1 <= r1 && l2 <= r2)
tr[tott] = v;
else
{
double X = jiao(tr[tott],v);
if (l1 >= r1)
{
if (X <= mid)
insert(lson[tott],l,mid,tr[tott]),tr[tott] = v;
else
insert(rson[tott],mid + ,r,v);
}
else
{
if (X > mid)
insert(rson[tott],mid + ,r,tr[tott]),tr[tott] = v;
else
insert(lson[tott],l,mid,v);
}
}
return;
} ll get(ll x,ll y)
{
return K[x] * y + B[x];
} ll getmin(ll tott,ll l,ll r,ll pos)
{
if (!tott)
return inf;
ll ans = get(tr[tott],pos);
ll mid = (l + r) >> ;
if (pos <= mid)
ans = min(ans,getmin(lson[tott],l,mid,pos));
else
ans = min(ans,getmin(rson[tott],mid + ,r,pos));
return ans;
} void solve2(ll sx,ll u,ll fa)
{
ans[sx] = min(ans[sx],ans[u] + b[u] * a[sx]);
insert(root,-maxx,maxx,u);
for (ll i = head[u];i;i = nextt[i])
{
ll v = to[i];
if (v == fa)
continue;
solve2(sx,v,u);
}
} void solve(ll u,ll fa)
{
if (!son[u]) //如果是叶子节点
{
K[u] = b[u];
B[u] = ;
insert(root,-maxx,maxx,u);
return;
}
for (ll i = head[u];i;i = nextt[i]) //先计算轻儿子
{
ll v = to[i];
if (v == son[u] || v == fa)
continue;
solve(v,u);
}
root = cnt = ; //消除轻儿子的贡献
solve(son[u],u); //计算重儿子的贡献
ans[u] = getmin(root,-maxx,maxx,a[u]);
for (ll i = head[u];i;i = nextt[i])
{
ll v = to[i];
if (v == son[u] || v == fa)
continue;
solve2(u,v,u); //计算轻儿子的答案
}
K[u] = b[u];
B[u] = ans[u];
insert(root,-maxx,maxx,u); //插入当前线段
} int main()
{
scanf("%I64d",&n);
for (ll i = ; i <= n; i++)
scanf("%I64d",&a[i]);
for (ll i = ; i <= n; i++)
scanf("%I64d",&b[i]);
for (ll i = ; i < n; i++)
{
ll x,y;
scanf("%I64d%I64d",&x,&y);
add(x,y);
add(y,x);
}
dfs(,);
solve(,);
for (ll i = ; i <= n; i++)
printf("%I64d ",ans[i]); return ;
}

   

 

   

Codeforces 932.F Escape Through Leaf的更多相关文章

  1. Codeforces Round #463 F. Escape Through Leaf (李超线段树合并)

    听说正解是啥 set启发式合并+维护凸包+二分 根本不会啊 , 只会 李超线段树合并 啦 ... 题意 给你一颗有 \(n\) 个点的树 , 每个节点有两个权值 \(a_i, b_i\) . 从 \( ...

  2. 【CF932F】Escape Through Leaf 启发式合并set维护凸包

    [CF932F]Escape Through Leaf 题意:给你一棵n个点的树,每个点有树形ai和bi,如果x是y的祖先,则你可以从x花费$a_x\times b_y$的费用走到y(费用可以为负). ...

  3. CF932F Escape Through Leaf

    CF932F Escape Through Leaf 首先, $ O(n^2) $ dp 是很显然的,方程长这样: \[dp[u] = min\{dp[v] + a_u\times b_v\} \] ...

  4. Codeforces 959 F. Mahmoud and Ehab and yet another xor task

    \(>Codeforces\space959 F. Mahmoud\ and\ Ehab\ and\ yet\ another\ xor\ task<\) 题目大意 : 给出一个长度为 \ ...

  5. Codeforces 835 F. Roads in the Kingdom

    \(>Codeforces\space835 F. Roads in the Kingdom<\) 题目大意 : 给你一棵 \(n\) 个点构成的树基环树,你需要删掉一条环边,使其变成一颗 ...

  6. Codeforces 731 F. Video Cards(前缀和)

    Codeforces 731 F. Video Cards 题目大意:给一组数,从中选一个数作lead,要求其他所有数减少为其倍数,再求和.问所求和的最大值. 思路:统计每个数字出现的个数,再做前缀和 ...

  7. CodeForces 1042 F Leaf Sets 贪心

    Leaf Sets 题意:给你一棵树,树上有n个点,只有一条边的点叫做叶子,现在要求把所有的叶子分组,每个组内的所有叶子的距离都不能大于k. 题解: 我们可以随意找一个不是叶子的节点当做这颗树的根节点 ...

  8. @codeforces - 932F@ Escape Through Leaf

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 n 个点的树(标号1~n),以结点 1 为根.每个结点 ...

  9. Codeforces 932 E. Team Work(组合数学)

    http://codeforces.com/contest/932/problem/E 题意:   可以看做 有n种小球,每种小球有无限个,先从中选出x种,再在这x种小球中任选k个小球的方案数 选出的 ...

随机推荐

  1. NO.07--我跟“ 币乎 ”的那些事

    文章开头给大家安利一款app吧,就是我标题提到的,‘币乎’,一个近似于虚拟货币的论坛吧,大家可以下载试试,发文章点赞赚钱,... 好了,开始说一说今天的正题吧: 这些事情说起来其实挺惭愧的,但也不是什 ...

  2. 从武侠中的兵器看待数据访问工具——Hibernate Spring.Data Mybatis

    <泪痕剑>第31集,卓爷大谈自己的兵器,我从中摘录,觉得非常受用. “你错了,我们和武器之间的关系,就好像选择情人一样,不管是否擅长,都要用感情. 我少年时候用刀,青年时候仍用刀,不知道用 ...

  3. scrapy-redis+selenium+webdriver 部署到linux上

    背景:在使用selenium时,在本地使用windows,都会有一个图形界面,但是到了生产环境linux上没有了图形界面怎么部署呢? 解决方案: 1.安装图形化界面,不推荐,因为安装图形化界面会占用很 ...

  4. activemq 持久化

    转自: http://blog.csdn.net/kobejayandy/article/details/50736479 消息持久性的原理很简单,就是在发送者将消息发送出去后,消息中心首先将消息存储 ...

  5. (转)一篇写的简明易懂的logging模块

    转:http://kenby.iteye.com/blog/1162698 一.从一个使用场景开始 开发一个日志系统, 既要把日志输出到控制台, 还要写入日志文件 import logging # 创 ...

  6. Asphalting Roads(翻译!)

    Description City X consists of n vertical and n horizontal infinite roads, forming n × n intersectio ...

  7. 第二次程序+PSP0级

    第二周,老师接着上次的程序有对四则运算的程序,做出来一些要求,这次要求可以控制乘除法,有无括号,控制输出方式,控制结果有无负数,有无余数. 我在对原先的程序分析了一下,发现我原先的程序可扩展性特别差, ...

  8. 2018软工实践—Alpha冲刺(4)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助前后端接口的开发 测试项目运行的服务器环 ...

  9. L1正则化与L2正则化的理解

    1. 为什么要使用正则化   我们先回顾一下房价预测的例子.以下是使用多项式回归来拟合房价预测的数据:   可以看出,左图拟合较为合适,而右图过拟合.如果想要解决右图中的过拟合问题,需要能够使得 $ ...

  10. DB2 9.5 数据库分区管理及应用实践

    DB2 数据库分区是 DB2 企业版 DPF(Data Partitioning Feature)选件提供的,它主要用来为大规模数据处理.高并发数据访问提供支持.DB2 数据库分区采用 Share-n ...