题目链接: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. VMware安装ubuntu虚拟机

    创建虚拟机完成. 安装操作系统. 中文版界面: 中文版界面: 稍等在重启 重新启动虚拟机. 安装VMtools 双击该图标 安装完成,重新启动系统. 如果在安装的时候,主机名没有修改 看着太长 如何修 ...

  2. angularjs中ckeditor的destroy问题

    项目中,在切换了页面的tab页后会发现上传图片的操作报错,检查后发现问题根源是切换了tab页重新加载页面时ckeditor又会创建一次,这个时候的ckeditor已经不是第一次创建的那个了,所以上传图 ...

  3. no module named flask.ext.login

    在用安装了flask-login后使用时发现了问题,查了许多资料尝试了许多办法: 1.以为是文件结构的问题,因为flask-login包中没有__init__.py结果编译后还是不行 2.以为是路径问 ...

  4. CLion 2016.1.1 下载 附注册激活码 破解版方法

    http://www.520xiazai.com/soft/CLion-2016.1.1.html CLion 2016.1.1 下载 附注册激活码 破解版方法 注册破解方法:在要求输入注册的界面选择 ...

  5. webpack入坑之旅

    转自: http://guowenfh.github.io/2016/03/24/vue-webpack-01-base/ http://guowenfh.github.io/2016/03/25/v ...

  6. [Unity] Shader(着色器)输入输出和语义

    在Unity5.x后, 已经支持了基于物理的光照模型,也就是常说的次时代引擎所必须具备的功能. 如果在Properties使用2D,CG里要用sampler2D,代表使用的是2维纹理 如果在Prope ...

  7. 浅谈Android中的startActivityForResult和setResult方法

    引言 我们知道,如果想打开一个新的Activity我们可以使用startActivity方法.今天我们介绍的startActivityForResult不仅可以打开全新的Activity,而且当新的A ...

  8. Mysql导入数据命令

    转自:http://blog.sina.com.cn/s/blog_610997850100mwv8.html 今天碰到个问题要用phpmyadmin导入1G的数据,但是在怎么都导入不了,用命令行就可 ...

  9. Alpha版本十天冲刺——Day 5

    站立式会议 会前小侃:今天是双11,也是恰逢组内秋鑫同学生日,本组同学祝他双11生日快乐.天气好冷,注意保暖. 会议总结 队员 今天完成 遇到的问题 明天要做 感想 鲍亮 json数据解析学习,完成注 ...

  10. 【Android学习】android布局中几个距离单位的区别:px、dp、sp

    一.px 像素,我们经常说的400*800这种的就是像素,这个比较好理解. 二.dp 要理解dp,首先要先引入dpi这个概念,dpi全称是dots per inch,对角线每英寸的像素点的个数,所以, ...