The merchant

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 4800   Accepted: 1666

Description

There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and wants to earn as much money as possible in each path. When he move along a path, he can choose one city to buy some goods and sell them in a city after it. The goods in all cities are the same but the prices are different. Now your task is to calculate the maximum possible profit on each path.

Input

The first line contains N, the number of cities. Each of the next N lines contains wi the goods' price in each city. Each of the next N-1 lines contains labels of two cities, describing a road between the two cities. The next line contains Q, the number of paths. Each of the next Q lines contains labels of two cities, describing a path. The cities are numbered from 1 to N.

1 ≤ NwiQ ≤ 50000

Output

The output contains Q lines, each contains the maximum profit of the corresponding path. If no positive profit can be earned, output 0 instead.

Sample Input

4
1
5
3
2
1 3
3 2
3 4
9
1 2
1 3
1 4
2 3
2 1
2 4
3 1
3 2
3 4

Sample Output

4
2
2
0
0
0
0
2
0

Source

大致翻译:有n个城市,n-1条边,现在一个商人要去买卖东西,每个城市都有固定的价格,现在有q条路径,问你每条路径上买卖能赚到的最多的钱分别是多少?一条路径只能顺着走,不能反过来.
分析:这道题巨坑爹整整调了一个下午TAT.回到正题,其实题目给我们n个城市,n-1条边就相当于给了我们一棵树,既然是告诉了树上两个点,我们肯定是要把LCA求出来才能知道两个点之间的路径的。求LCA可以利用倍增,那么接下来就要维护一些信息才能完成此题。
     假设有一个询问是(u,v),u,v的LCA为t,那么我们可能在u到t的这段路径买入,在t到v的这段路径卖出,也可能就在u到t的这段路径买入卖出,还可能在t到v的这段路径买入卖出.考虑第一种情况,我们需要记录u到t的最小值和t到v的最大值,考虑第二种情况和第三种情况,我们只需要分别维护这两段路径上的最大收益即可,但是注意从t到v的这段路径,我们倍增总不能从t跳到v吧,我们让u和v往上跳,那么考虑反过程,我们让从v到t的这段路径在价格最高点买入,在价格最低点卖出,统计答案的时候取相反数即可。
     上面说明了我们要维护哪些信息,下面来说明该怎么维护这些信息:
     设minn[i][j]为i到i的第2^j个祖先的最小值,maxx[i][j]为为i到i的第2^j个祖先的最大值,lmax[i][j]为i到i的第2^j个祖先的最大收益,rmin[i][j]为i到i的第2^j个祖先的最小收益(刚刚考虑的特殊情况),fa[i][j]为i的第2^j个祖先。
     可以先利用dfs求出fa[i][0]和每个节点的深度d[i],然后发现:我们可以在维护fa[i][j]的同时维护其他信息:minn[i][j] = min(minn[i][j-1],minn[fa[i][j-1]][j-1]),maxx类同,那么lmax就是最大卖出价-最小买入价,或者是它的子区间中的最大值,即lmax[i][j] = max(max(lmax[i][j - 1], lmax[fa[i][j - 1]][j - 1]), maxx[fa[i][j-1]][j - 1] - minn[i][j - 1]),rmin类同,顺序不能反!
     然后我们需要在倍增的时候处理这些信息。以求从u到t的这段路径为例,维护最小值,最大收益,怎么维护最大收益呢?利用之前的lmax数组和maxx数组和当前维护的最小值,然后维护从t到u的信息。最后的答案可能有3种:从u到t的最大收益,从t到v的最小收益的相反数,从t到v的最大值减去从u到t的最小值,取这3种可能的答案的最大值即可。
还有一些小细节,可以在代码中查看:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; int n,a[],head[],to[],nextt[],tot,q,d[];
int fa[][], minn[][], maxx[][], lmax[][], rmin[][]; void add(int x, int y)
{
to[tot] = y;
nextt[tot] = head[x];
head[x] = tot++;
} void dfs(int u, int from,int dist)
{
d[u] = dist;
fa[u][] = from;
for (int i = head[u]; i != -; i = nextt[i])
{
int v = to[i];
if (from != v)
dfs(v, u,dist + );
}
} void init()
{
dfs(, , );
minn[][] = maxx[][] = a[];
lmax[][] = - << ;
rmin[][] = << ;
for (int i = ; i <= n; i++)
{
minn[i][] = min(a[i], a[fa[i][]]);
maxx[i][] = max(a[i], a[fa[i][]]);
lmax[i][] = max(a[fa[i][]] - a[i], );
rmin[i][] = min(a[fa[i][]] - a[i], );
}
for (int j = ; ( << j) < n; j++)
for (int i = ; i <= n; i++)
{
fa[i][j] = fa[fa[i][j - ]][j - ];
maxx[i][j] = max(maxx[i][j - ], maxx[fa[i][j - ]][j - ]);
minn[i][j] = min(minn[i][j - ], minn[fa[i][j - ]][j - ]);
lmax[i][j] = max(max(lmax[i][j - ], lmax[fa[i][j - ]][j - ]), maxx[fa[i][j-]][j - ] - minn[i][j - ]);
rmin[i][j] = min(min(rmin[i][j - ], rmin[fa[i][j - ]][j - ]), minn[fa[i][j - ]][j - ] - maxx[i][j - ]);
}
} int LCA(int x, int y)
{
int maxxx = , miny = , minx = a[x], maxy = a[y];
for (int i = ; i >= && d[x] != d[y]; i--)
{
if (abs(d[x] - d[y]) >= << i)
{
if (d[y] < d[x])
{
maxxx = max(max(maxxx, lmax[x][i]), maxx[x][i] - minx);
minx = min(minx, minn[x][i]);
x = fa[x][i];
}
else
{
miny = min(min(miny, rmin[y][i]), minn[y][i] - maxy);
maxy = max(maxy, maxx[y][i]);
y = fa[y][i];
}
}
}
if (x == y)
return max(max(maxxx, -miny), maxy - minx);
for (int i = ; i >= ;i--)
if (fa[x][i] != fa[y][i] && fa[x][i] && fa[y][i])
{
maxxx = max(max(maxxx, lmax[x][i]), maxx[x][i] - minx);
minx = min(minx, minn[x][i]);
x = fa[x][i]; miny = min(min(miny, rmin[y][i]), minn[y][i] - maxy);
maxy = max(maxy, maxx[y][i]);
y = fa[y][i];
}
maxxx = max(max(maxxx, lmax[x][]), maxx[x][] - minx);
minx = min(minx, minn[x][]);
miny = min(min(miny, rmin[y][]), minn[y][] - maxy);
maxy = max(maxy, maxx[y][]);
return max(max(maxxx, -miny), maxy - minx); } int main()
{
memset(head, -, sizeof(head));
scanf("%d", &n);
for (int i = ; i <= n; i++)
scanf("%d", &a[i]);
for (int i = ; i <= n - ; i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
init();
scanf("%d", &q);
while (q--)
{
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", LCA(x, y));
} return ;
}

poj3728The merchant的更多相关文章

  1. poj3728The merchant 【倍增】【LCA】

    There are N cities in a country, and there is one and only one simple path between each pair of citi ...

  2. POJ3728The merchant (倍增)(LCA)(DP)(经典)(||并查集压缩路径?)

    There are N cities in a country, and there is one and only one simple path between each pair of citi ...

  3. poj3728The merchant树剖+线段树

    如果直接在一条直线上,那么就建线段树 考虑每一个区间维护最小值和最大值和答案,就符合了合并的条件,一个log轻松做 那么在树上只要套一个树剖就搞定了,多一个log也不是问题 注意考虑在树上的话每一条链 ...

  4. [最近公共祖先] POJ 3728 The merchant

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4556   Accepted: 1576 Desc ...

  5. POJ 3278 The merchant

    传送门 Time Limit: 3000MS Memory Limit: 65536K Description There are N cities in a country, and there i ...

  6. poj 3728 The merchant(LCA)

    Description There are N cities in a country, and there is one and only one simple path between each ...

  7. ThoughtWorks Merchant's Guide To The Galaxy

    ThoughtWorks笔试题之Merchant's Guide To The Galaxy解析 一.背景 在某网站上看到ThoughtWorks在武汉招人,待遇在本地还算不错,就投递了简历.第二天H ...

  8. [POJ 3728]The merchant

    Description There are N cities in a country, and there is one and only one simple path between each ...

  9. opencart3图片Google Merchant Center验证通过不了的解决方法

    最近在做一个opencart项目,有对接Google Merchant Center,但是一直提示产品图片验证无法通过,ytkah看了一下图片路径,/image/cache/catalog/demo/ ...

随机推荐

  1. 使用HelpProvide组件调用帮助文件

    实现效果: 知识运用: HelpProvider组件的HelpNameSpace属性 //于对象关联的帮助文件名 public virtual string HelpNameSpace {get; s ...

  2. python基础一 day15 面试题

    # def demo():# for i in range(4):# yield i## g=demo()## g1=(i for i in g)# g2=(i for i in g1)## prin ...

  3. JavaScript 获取对象中第一个属性

    使用 Object.keys(object) 可以取出属性名为数组,但会打乱顺序 严格意义上对象中是只有映射关系而没有顺序的,但是在存储结构里是有顺序的,如果想获取存储结构里的第一个属性可以使用for ...

  4. win7便笺元数据损坏,最新解决办法

    Windows7系统开机时出现“部分便笺的元数据已被破坏,便笺已将其恢复为默认值.”问题,最新解决办法,图文说明,亲测,希望可以帮到大家 工具/原料   Windows7系统 InkObj.dll.T ...

  5. jsp页面之间传值 以及如何取出url的参数

    写项目时往往要写多个页面,而多个jsp之间传值有时是必要的,这时可以用到如下方法: 而在另一个页面取值可以用:${param.xxx}   此处的xxx就是要传递的值

  6. JS实用技术

    JS外部引用其他文件(建议) <script src="myScript1.js"></script> JS输出显示方式 使用 window.alert() ...

  7. 使用js将div高度设置为100%

      在开发的工程中使用到了一些开源的bootstrap模板进行开发,在遇到一些需要替换的内容部分部分时,经常出现高度设置100%无法生效的问题,这里来用js强行设置一下.   思路:js监听窗口的缩放 ...

  8. k8s的资源限制及资源请求

    容器的资源需求及限制:  需求:requests   ##定义容器运行时至少需要资源  限制:limits     ##定义容器运行时最多能分配的资源    requests:pod.spec.con ...

  9. MySQL中CONCAT()的用法

    MySQL中CONCAT()的用法 在日常开发过程中,特别是在书写接口的时候,经常会遇到字符串拼接的情况,比如在返回图片数据时,数据库里往往存储的是相对路径,而接口里一般是存放绝对地址,这就需要字符串 ...

  10. 15.Yii2.0框架where单表查询

    目录 新建控制器 HomeController.php 新建model article.php 新建控制器 HomeController.php D:\xampp\htdocs\yii\control ...