题目链接:http://poj.org/problem?id=3728

思路:题目的意思是求树上a -> b的路径上的最大收益(在最小值买入,在最大值卖出)。

我们假设路径a - > b 之间的LCA(a, b) = f, 并且另up[a]表示a - > f之间的最大收益,down[a]表示f - > a之间的最大收益,dp_max[a]表示a - > f之间的最大值,dp_min[a]表示a - > f之间的最小值,于是可以得出关系: ans[id] = max(max(up[a], down[b]), dp_max[b] - dp_min[a])。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAX_N = (50000 + 5000);
const int MAX_M = (MAX_N << 2);
const int inf = 0x3f3f3f3f;
int NE1, NE2, NE3, head1[MAX_N], head2[MAX_N], head3[MAX_N]; void Init()
{
NE1 = NE2 = NE3 = 0;
memset(head1, -1, sizeof(head1));
memset(head2, -1, sizeof(head2));
memset(head3, -1, sizeof(head3)); } int N, Q, ans[MAX_N], value[MAX_N], vis[MAX_N]; struct Edge1 {
int v, next;
} edge1[MAX_M]; void Insert1(int u, int v)
{
edge1[NE1].v = v;
edge1[NE1].next = head1[u];
head1[u] = NE1++;
} struct Edge {
int v, id, next;
} edge2[MAX_M], edge3[MAX_M]; void Insert2(int u, int v, int id, int flag)
{
if (!flag) {
edge2[NE2].v = v;
edge2[NE2].id = id;
edge2[NE2].next = head2[u];
head2[u] = NE2++;
} else {
edge3[NE3].v = v;
edge3[NE3].id = id;
edge3[NE3].next = head3[u];
head3[u] = NE3++;
}
} int parent[MAX_N];
int up[MAX_N], down[MAX_N], dp_max[MAX_N], dp_min[MAX_N]; int find(int x)
{
if (x == parent[x]) {
return x;
} int fa = parent[x];
parent[x] = find(parent[x]); up[x] = max(max(up[x], up[fa]), dp_max[fa] - dp_min[x]);
down[x] = max(max(down[x], down[fa]), dp_max[x] - dp_min[fa]);
dp_max[x] = max(dp_max[x], dp_max[fa]);
dp_min[x] = min(dp_min[x], dp_min[fa]); return parent[x];
} struct Node {
int u, v;
} node[MAX_N]; void Tarjan(int u)
{
vis[u] = 1;
parent[u] = u;
//Q;
for (int i = head2[u]; ~i; i = edge2[i].next) {
int v = edge2[i].v, id = edge2[i].id;
if (!vis[v]) continue;
int fa = find(v);
Insert2(fa, v, id, 1);
} for (int i = head1[u]; ~i; i = edge1[i].next) {
int v = edge1[i].v;
if (vis[v]) continue;
Tarjan(v);
parent[v] = u;
} //edge3
for (int i = head3[u]; ~i; i = edge3[i].next) {
int id = edge3[i].id;
find(node[id].u);
find(node[id].v);
ans[id] = max(max(up[node[id].u], down[node[id].v]), dp_max[node[id].v] - dp_min[node[id].u]);
}
} int main()
{
while (~scanf("%d", &N)) {
for (int i = 1; i <= N; ++i) {
scanf("%d", &value[i]);
up[i] = down[i] = 0;
dp_max[i] = dp_min[i] = value[i];
} Init(); for (int i = 1; i < N; ++i) {
int u, v;
scanf("%d %d", &u, &v);
Insert1(u, v);
Insert1(v, u);
} scanf("%d", &Q);
for (int i = 1; i <= Q; ++i) {
scanf("%d %d", &node[i].u, &node[i].v);
Insert2(node[i].u, node[i].v, i, 0);
Insert2(node[i].v, node[i].u, i, 0);
} memset(vis, 0, sizeof(vis));
Tarjan(1); for (int i = 1; i <= Q; ++i) printf("%d\n", ans[i]);
}
return 0;
}



poj 3728(LCA + dp)的更多相关文章

  1. Fire (poj 2152 树形dp)

    Fire (poj 2152 树形dp) 给定一棵n个结点的树(1<n<=1000).现在要选择某些点,使得整棵树都被覆盖到.当选择第i个点的时候,可以覆盖和它距离在d[i]之内的结点,同 ...

  2. POJ 3728 The merchant(LCA+DP)

    The merchant Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total ...

  3. poj 3728 The merchant 倍增lca求dp

    题目: zdf给出的题目翻译: 从前有一个富饶的国度,在这里人们可以进行自由的交易.这个国度形成一个n个点的无向图,每个点表示一个城市,并且有一个权值w[i],表示这个城市出售或收购这个权值的物品.又 ...

  4. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

  5. 【题解】POJ 3417 Network(倍增求LCA+DP+树上差分)

    POJ3417:http://poj.org/problem?id=3417 思路 我们注意到由“主要边”构成一颗树 “附加边”则是非树边 把一条附加边(x,y)加入树中 会与树上x,y之间构成一个环 ...

  6. poj 3417 树形dp+LCA

    思路:我以前一直喜欢用根号n分段的LCA.在这题上挂了,第一次发现这样的LCA被卡.果断改用Tarjan离线算法求LCA. 当前节点为u,其子节点为v.那么: 当以v根的子树中含有连接子树以外点的边数 ...

  7. poj 3728 The merchant(LCA)

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

  8. POJ 3278:The merchant(LCA&DP)

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6864   Accepted: 2375 Desc ...

  9. POJ 3728 The merchant(并查集+DFS)

    [题目链接] http://poj.org/problem?id=3728 [题目大意] 给出一棵树,每个点上都可以交易货物,现在给出某货物在不同点的价格, 问从u到v的路程中,只允许做一次买入和一次 ...

随机推荐

  1. BZOJ 2946: [Poi2000]公共串

    2946: [Poi2000]公共串 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 342[Submit][Status][D ...

  2. BZOJ 1086: [SCOI2005]王室联邦

    1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1399  Solved: ...

  3. bzoj2086【Poi2010】Blocks

    因为long long还有PE的事WA了一下午TAT 考虑一段可行区间的平均值肯定>=k 也就是说将每个数减去k以后,一段可行区间的和非负,求一段最长区间. 一段区间的和肯定是两个前缀和的差 先 ...

  4. TypeScript Declaration Merging(声明合并)

    TypeScript中有一些独特的概念,来自需要描述JavaScript对象类型发生了哪些变化.举个例子,最为独特的概念就是"声明合并".理解了这个概念将会对你在当前JavaScr ...

  5. <<< web里面Servlet高级应用的基础介绍

    Servlet中的页面跳转?两种方式,实现跳转:内部跳转(请求转发).外部跳转(重定向)内部跳转(请求转发)特点:在服务器内部完成页面之间的跳转:请求只有一次:浏览器地址不会改变.request.ge ...

  6. 100_1小记ressons analysis

    想到一首诗用以自勉: look to the master, follow the master, walk with the master, see through the master, beco ...

  7. 出现could not find developer disk image解决办法和不受信任的开发者

    真机测试问题 最近一直遇到这样的问题,很是让人心烦,但是还是要自己解决的,我也是从网上查了很多这样的解决办法,都没有成功,所以今天我要把自己的总结的方法和大家分享一下. iOS测试当中的问题 iOS ...

  8. js动态添加的元素不能绑定事件

    动态生成的元素,使用.on绑定事件,比如$(document).on("click",".divclick",function(){})

  9. PHP读写大“二进制”文件,不必申请很大内存(fopen、fread、fwrite、fclose)

    <?php /** * 读写大二进制文件,不必申请很大内存 * 只有读取到内容才创建文件 * 保证目录可写 * * @param string $srcPath 源文件路径 * @param s ...

  10. javascript基础04

    javascript基础04 1.循环语句 1.While 语句: while (exp) { //statements; } var i = 1; while(i < 3){ alert(i) ...