题目链接: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. Python项目之我的第一个爬虫----爬取豆瓣图书网,统计图书数量

    今天,花了一个晚上的时间边学边做,搞出了我的第一个爬虫.学习Python有两个月了,期间断断续续,但是始终放弃,今天搞了一个小项目,有种丰收的喜悦.废话不说了,直接附上我的全部代码. # -*- co ...

  2. BZOJ4540 [Hnoi2016]序列

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  3. gulp打包js/css时合并成一个文件时的顺序解决

    1.可以使用插进gulp-order. 2.可以这样的写法: return gulp.src(['js/common.js','js/**/*.js']) .pipe(concat('build.js ...

  4. 优化php代码 - 字符串echo输出 逗号也可作php连接符

    2016年12月12日10:00:16 ====================== 网页访问速度的提升,是可以通过代码的优化来实现的.代码的优化,并不是说代码越少越好,而是主要看代码的运行能力和执行 ...

  5. yii2 session的使用方法

    yii2打开session use yii\web\Session; $session = Yii::$app->session; // check if a session is alread ...

  6. Android ViewPager sharedpreferences

    http://www.cnblogs.com/dwinter/archive/2012/02/27/AndroidViewPager%E5%A4%9A%E9%A1%B5%E9%9D%A2%E6%BB% ...

  7. Java实现Excel的操作

    JAVA EXCEL API: 开源项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Windows操作系统也可以通过纯Ja ...

  8. PHP realpath() 函数

    定义和用法 realpath() 函数返回绝对路径. 该函数删除所有符号连接(比如 '/./', '/../' 以及多余的 '/'),返回绝对路径名. 若失败,则返回 false.比如说文件不存在的话 ...

  9. Shell入门教程:流程控制(4)case 条件判断

    case的语法结构: case 待测项 in 样式串1] 命令区域1 ;; (样式串2) 命令区域2 ;; 样式串3) 命令区域3 ;; *) 命令区域 ;; esac 命令区域,可以是单一指令或多行 ...

  10. redis中的key设置过期时间

    EXPIRE key seconds 为给定  key  设置生存时间,当  key  过期时(生存时间为  0  ),它会被自动删除. 在 Redis 中,带有生存时间的  key  被称为『易失的 ...