POJ3728 The merchant解题报告
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 ≤ N, wi, Q ≤ 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
- 分析:
- 首先n个点只有n-1条边,又保证每两个点之间只有一条路径,明显是一颗树。
- 题目就变成了找到两个点之间的路径,求出路径后再要求出最大收益便非常简单。
- 求一颗树中两点的路径可以用最近公共祖先算法
- 还可以在求LCA的同时将最大收益更新出来,只需要记录几个值即可。
- 如果是要边找边求的话使用离线的tarjan算法,只要记录几个值,便可。
- 由于对倍增法不太熟悉所以用这道题来熟悉倍增法
- 代码在这里
- #include <cstdio>
- #include <vector>
- #define INF 55555
- using namespace std;
- struct record {
- int x, upMax, doMax, pMin, pMax;
- };
- int nPrice[INF], nSnode[INF];
- int nDeep[INF];
- record pNode[INF][18];
- bool vis[INF];
- const int Pow = 17;
- vector<int> g[INF];
- //dfs 求出所需值
- void dfs (int u, int fa) {
- vis[u] = true, nDeep[u] = nDeep[fa] + 1, pNode[u][0].x = fa;
- //pNode记录从节点向上2^j个节点中最大收益upMAX,
- //从最上节点到u的最大收益domax,和最大价格最小价格pMax,pMin
- pNode[u][0].pMin = min (nPrice[u], nPrice[fa]);
- pNode[u][0].pMax = max (nPrice[u], nPrice[fa]);
- pNode[u][0].upMax = max (0, nPrice[fa] - nPrice[u]),;
- pNode[u][0].doMax = max (nPrice[u] - nPrice[fa], 0);
- //dp更新pNode
- for (int i = 1; i <= Pow; i++) {
- int j = pNode[u][i - 1].x;
- pNode[u][i].x = pNode[j][i - 1].x;
- pNode[u][i].pMin = min (pNode[u][i - 1].pMin, pNode[j][i - 1].pMin);
- pNode[u][i].pMax = max (pNode[u][i - 1].pMax, pNode[j][i - 1].pMax);
- pNode[u][i].upMax = max (pNode[u][i - 1].upMax, pNode[j][i - 1].upMax);
- pNode[u][i].upMax = max (pNode[u][i].upMax,
- pNode[j][i - 1].pMax - pNode[u][i - 1].pMin);
- pNode[u][i].doMax = max (pNode[u][i - 1].doMax, pNode[j][i - 1].doMax);
- pNode[u][i].doMax = max (pNode[u][i].doMax,
- pNode[u][i - 1].pMax - pNode[j][i - 1].pMin);
- };
- int nSize = g[u].size();
- for (int i = 0; i < nSize; i++) {
- int v = g[u][i];
- if (v == fa || vis[v]) continue;
- dfs (v, u);
- }
- }
- int aMin, bMax, upDmax, doDmax, ans;
- //更新doDmax
- void makeb (int i, int &b) {
- doDmax = max (doDmax, pNode[b][i].doMax),;
- doDmax = max (doDmax, bMax - pNode[b][i].pMin);
- bMax = max (bMax, pNode[b][i].pMax);
- b = pNode[b][i].x;
- }
- //更新upDmax
- void makea (int i, int &a) {
- upDmax = max (upDmax, pNode[a][i].upMax),;
- upDmax = max (upDmax, pNode[a][i].pMax - aMin);
- aMin = min (aMin, pNode[a][i].pMin);
- a = pNode[a][i].x;
- }
- int bzlca (int a, int b) {
- aMin = nPrice[a], bMax = nPrice[b] ;
- upDmax = doDmax = 0;
- //将a,b置于同一层
- //将b向上提,更新向下到b的最大收益doDmax
- if (nDeep[a] < nDeep[b])
- for (int del = nDeep[b] - nDeep[a], i = 0; i < Pow; i++)
- if (del & (1 << i) ) makeb (i, b);
- //将a向上提,更新从a向上到的最大收益upDmax
- if (nDeep[a] > nDeep[b])
- for (int del = nDeep[a] - nDeep[b], i = 0; i < Pow; i++)
- if (del & (1 << i) ) makea (i, a);
- //找到a,b的最近公共祖先,同时更新从a向上到祖先的最大收益
- //从祖先向下到b的最大收益
- if (a != b) {
- for (int i = Pow ; i >= 0; i--)
- if (pNode[a][i].x != pNode[b][i].x) makea (i, a), makeb (i, b);
- makea (0, a), makeb (0, b);
- }
- ans = max (doDmax, upDmax), ans = max (ans, bMax - aMin);
- return ans;
- }
- int main() {
- int x, y, n, m;
- scanf ("%d", &n);
- for (int i = 1; i <= n; i++) scanf ("%d", &nPrice[i]);
- for (int i = 1; i < n; i++) {
- scanf ("%d %d", &x, &y);
- g[x].push_back (y), g[y].push_back (x);
- }
- dfs (1, 1);
- scanf ("%d", &m);
- for (int i = 1; i <= m; i++) {
- scanf ("%d %d", &x, &y);
- printf ("%d\n", bzlca (x, y) );
- }
- return 0;
- }
POJ3728 The merchant解题报告的更多相关文章
- 雅礼集训 Day6 T1 Merchant 解题报告
Merchant 题目描述 有\(n\)个物品,第\(i\)个物品有两个属性\(k_i,b_i\),表示它在时刻\(x\)的价值为\(k_i\times x+b_i\). 当前处于时刻\(0\),你可 ...
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- 习题: codevs 2492 上帝造题的七分钟2 解题报告
这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...
- 习题:codevs 1519 过路费 解题报告
今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...
- NOIP2016提高组解题报告
NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合
随机推荐
- 一种结合hudson的算法自动化测试构想
作者:朱金灿 来源:http://blog.csdn.net/clever101 有时我在思考:未来软件测试的趋势是什么?其实答案和其它行业一样简单:低技术含量的测试工作都将由机器承担,人只能干机器干 ...
- thinkphp查询,3.X 5.0 亲试可行
[php] view plain copy print? 一.介绍 ThinkPHP内置了非常灵活的查询方法,可以快速的进行数据查询操作,查询条件可以用于读取.更新和删除等操作,主要涉及到wher ...
- RDO、SAD、SATD、λ相关概念【转】
率失真优化概述: 率失真优化(Rate D isto r t i on Op t i m ized)策略是在率失真理论[3 ]的基础上提出的一种代价函数方案, RDO 的主要思想是, 在计算代价函数时 ...
- qt查找框设置
转载请注明出处:http://www.cnblogs.com/dachen408/p/7229129.html 主界面弹出查找框方法,查找框显示在主界面上层,并还可以点击主界面,非模态. class ...
- Vue 数组和对象更新,但是页面没有刷新
在使用数组的时候,数组内部数据发生改变,但是与数组绑定的页面的数据却没有发生变化. <ul> <li v-for="(item,index) in todos" ...
- golang zip 解压、压缩文件
package utils import ( "archive/zip" "fmt" "io" "io/i ...
- C# 實現文件壓縮-- 背景:服務器Log.txt 過多,佔用過多硬盤空間,壓縮備份后節省空間資源
1.壓縮實現代碼如下: 調用ICSharpCode.SharpZipLib.dll(free software,可以搜到源碼). 轉移指定目錄文件夾轉移到目標文件夾 壓縮目標文件夾 刪除目標文件夾 u ...
- mfc 菜单
创建一个基于对话框的工程,工程名为CreateMenu 为该对话框增加一个文件菜单项和测试菜单项,如下图所示 测试菜单项至少要有一个子菜单项 在对话框属性中关联该菜单 在resource.h中增加 ...
- WebDAV协议
WebDAV是一项基于 Http1.1 协议的通信协议.它扩展了HTTP 1.1,在Get.Post.Put.Delete 等HTTP标准方法外添加了新方法,使应用程序可对Web Server直接读写 ...
- gifsicle for linux ----------gif 图像处理
1.gifsicle 在linux 中的使用下载gifsicle yum install gifsicle 若发现没有此包 ,更新epel第三方软件库 sudo yum install epel-re ...