The merchant

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 6864   Accepted: 2375

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

题意

给出一棵树,每个节点有一个点权,代表商品的价值

从节点u->v的路径上,有一个商人从一个节点购买商品,并在另一个节点卖出,问商人可以获得的最大利润是多少

思路

商人进行买卖一共有三种情况:

  1. 在点u->lca(u,v)的路上买,lca(u,v)->v的路上卖
  2. 在u->lca(u,v)的路上完成买卖
  3. 在lca(u,v)->v的路上完成买卖

所以我们可以引入四个数组:up,down,maxx,minn。分别代表:在u->lca(u,v)的路上完成买卖的最大获利;在lca(u,v)->v的路上完成买卖的最大获利;lca(u,v)->v点出售的最大利润;u->lca(u,v)购买的最少花费

我们可以得到商人的最大收益=max(max(up[u],down[v]),maxx[v]-minn[u])

问题就变成了去寻找lca(u,v),并更新数组的值。以上四个数组的值可以在并查集find函数中进行更新

代码

  1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 #define ll long long
5 #define ull unsigned long long
6 #define ms(a,b) memset(a,b,sizeof(a))
7 const int inf=0x3f3f3f3f;
8 const ll INF=0x3f3f3f3f3f3f3f3f;
9 const int maxn=1e6+10;
10 const int mod=1e9+7;
11 const int maxm=1e3+10;
12 using namespace std;
13 int maxx[maxn],minn[maxn];
14 int up[maxn],down[maxn];
15 int f[maxn];
16 // minn[u] u->lca(u,v)买的最小值
17 // maxx[v] lca(u,v)->v卖的最大值
18 // up[u] u->lca(u,v)进行买卖的最大值
19 // down[v] lca(u,v)->v进行买卖的最大值
20 int find(int x)
21 {
22 if(f[x]==x)
23 return x;
24 int y=f[x];
25 f[x]=find(f[x]);
26 up[x]=max(max(up[y],up[x]),maxx[y]-minn[x]);
27 down[x]=max(max(down[y],down[x]),maxx[x]-minn[y]);
28 maxx[x]=max(maxx[x],maxx[y]);
29 minn[x]=min(minn[x],minn[y]);
30 return f[x];
31 }
32 void join(int x,int y)
33 {
34 int dx=f[x],dy=f[y];
35 if(dx!=dy)
36 f[y]=dx;
37 }
38 struct Edge
39 {
40 int to,Next;
41 }edge[maxn];
42 int head1[maxn];
43 int tot1;
44 void add_edge(int u,int v)
45 {
46 edge[tot1].to=v;
47 edge[tot1].Next=head1[u];
48 head1[u]=tot1++;
49 }
50 struct Query
51 {
52 int to,Next;
53 int index;
54 }query[maxn];
55 int head2[maxn];
56 int tot2;
57 void add_query(int u,int v,int index)
58 {
59 query[tot2].to=v;
60 query[tot2].Next=head2[u];
61 query[tot2].index=index;
62 head2[u]=tot2++;
63 }
64 struct Pos
65 {
66 int to,Next;
67 int index;
68 }pos[maxn];
69 int head3[maxn];
70 int tot3;
71 void add_pos(int u,int v,int index)
72 {
73 pos[tot3].to=v;
74 pos[tot3].Next=head3[u];
75 pos[tot3].index=index;
76 head3[u]=tot3++;
77 }
78 int vis[maxn];
79 int qu[maxn],qv[maxn];
80 int fa[maxn];
81 int ans[maxn];
82 void LCA(int u)
83 {
84 fa[u]=u;
85 vis[u]=1;
86 for(int i=head1[u];~i;i=edge[i].Next)
87 {
88 int v=edge[i].to;
89 if(vis[v])
90 continue;
91 LCA(v);
92 join(u,v);
93 fa[find(u)]=u;
94 }
95 for(int i=head2[u];~i;i=query[i].Next)
96 {
97 int v=query[i].to;
98 if(vis[v])
99 {
100 int t=fa[find(v)];
101 // 储存lca(u,v)的子节点
102 add_pos(t,v,query[i].index);
103 }
104 }
105 for(int i=head3[u];~i;i=pos[i].Next)
106 {
107 int id=pos[i].index;
108 int xx=qu[id],yy=qv[id];
109 // 更新四个数组的值
110 find(xx);find(yy);
111 ans[id]=max(max(up[xx],down[yy]),maxx[yy]-minn[xx]);
112 }
113 }
114 int value[maxn];
115 void init(int n)
116 {
117 tot1=0;tot2=0;tot3=0;
118 for(int i=1;i<=n;i++)
119 f[i]=i;
120 ms(fa,0);ms(vis,0);
121 ms(head1,-1);ms(head2,-1);ms(head3,-1);
122 }
123 int main(int argc, char const *argv[])
124 {
125 #ifndef ONLINE_JUDGE
126 freopen("/home/wzy/in.txt", "r", stdin);
127 freopen("/home/wzy/out.txt", "w", stdout);
128 srand((unsigned int)time(NULL));
129 #endif
130 ios::sync_with_stdio(false);
131 cin.tie(0);
132 int n;
133 cin>>n;
134 init(n);
135 for(int i=1;i<=n;i++)
136 cin>>value[i],minn[i]=value[i],maxx[i]=value[i];
137 int u,v;
138 for(int i=1;i<n;i++)
139 cin>>u>>v,add_edge(u,v),add_edge(v,u);
140 int q;
141 cin>>q;
142 for(int i=0;i<q;i++)
143 cin>>qu[i]>>qv[i],add_query(qu[i],qv[i],i),add_query(qv[i],qu[i],i);
144 LCA(1);
145 for(int i=0;i<q;i++)
146 cout<<ans[i]<<"\n";
147 #ifndef ONLINE_JUDGE
148 cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<" s."<<endl;
149 #endif
150 return 0;
151 }

POJ 3278:The merchant(LCA&DP)的更多相关文章

  1. POJ 3728 The merchant(LCA+DP)

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

  2. POJ 1651:Multiplication Puzzle(区间DP)

    http://poj.org/problem?id=1651 题意:给出n个数字,每取中间一个数,就会使得权值加上中间这个数和两边的乘积,求取剩两个数最少的权值是多少. 思路:区间dp. 一开始想了挺 ...

  3. CodeForces - 1073E :Segment Sum (数位DP)

    You are given two integers l l and r r (l≤r l≤r ). Your task is to calculate the sum of numbers from ...

  4. POJ 2796:Feel Good(单调栈)

    http://poj.org/problem?id=2796 题意:给出n个数,问一个区间里面最小的元素*这个区间元素的和的最大值是多少. 思路:只想到了O(n^2)的做法. 参考了http://ww ...

  5. POJ 3318:Matrix Multiplication(随机算法)

    http://poj.org/problem?id=3318 题意:问A和B两个矩阵相乘能否等于C. 思路:题目明确说出(n^3)的算法不能过,但是通过各种常数优化还是能过的. 这里的随机算法指的是随 ...

  6. SPOJ:House Fence(分治&DP)

    "Holiday is coming, holiday is coming, hurray hurray!" shouts Joke in the last day of his ...

  7. BZOJ 1026:windy数(数位DP)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1026 1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memor ...

  8. POJ 1200:Crazy Search(哈希)

    Crazy Search Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32483   Accepted: 8947 Des ...

  9. poj 2533 Longest Ordered Subsequence(线性dp)

    题目链接:http://poj.org/problem?id=2533 思路分析:该问题为经典的最长递增子序列问题,使用动态规划就可以解决: 1)状态定义:假设序列为A[0, 1, .., n],则定 ...

随机推荐

  1. 使用Rainbond实现离线环境软件交付

    一.离线交付的痛点 在传统行业,如政府.能源.军工.公安.工业.交通等行业,为了防止数据泄露和运行安全考虑,一般情况下网络会采取内外网隔离的策略,以防范不必要的风险,毕竟在安全防护方面,网络物理隔离是 ...

  2. C++中的排序

    下面网站解释比较好 http://www.cnblogs.com/heyonggang/archive/2013/11/03/3404371.html 1. qsort(C中的函数加上stdlib.h ...

  3. 『学了就忘』Linux文件系统管理 — 67、通过命令模式进行LVM分区

    目录 1.物理卷管理 (1)准备硬盘或者分区 (2)建立物理卷 (3)查看物理卷 (3)删除物理卷 2.创建卷组 (1)建立卷组 (2)查看卷组 (3)增加卷组容量 (4)减小卷组容量 (5)删除卷组 ...

  4. 案例分析 CAN OPEN 调试记录 进度

    2020.12.29 发现一片博客:https://blog.csdn.net/harrycomeon/article/details/94650103 需要一个硬件:CAN分析仪,网上200元左右. ...

  5. OpenStack之之一: 快速添加计算节点

    根据需求创建脚本,可以快速添加节点#:初始化node节点 [root@node2 ~]# systemctl disable NetworkManager [root@node2 ~]# vim /e ...

  6. Dubbo应用到web工程

    一.创建提供者03-provider-web (1) 创建工程 创建Maven的web工程,然后创建实现类. (2) 导入依赖 Spring的版本为4.3.16 需要的依赖有: dubbo2.7.0版 ...

  7. jQuery - 按回车键触发跳转

    键盘事件有三种: keyup:按键按下去,抬上来后,事件才生效 (推荐) keydown:按键按下去就生效 keypress:与 keydown 事件类似,当按钮被按下时,会发生该事件,与 keydo ...

  8. IT过来人的10点经验谈

    1 入行要趁早,正常是22岁本科或25岁硕士毕业入行.如果是零基础经培训班加持的,尽量在28岁前入行,30岁以后再想要入行IT的,千万慎重. 2 IT行业确实能挣大钱,而且能为学历一般学校一般家庭背景 ...

  9. [BUUCTF]PWN——[BJDCTF 2nd]test

    [BJDCTF 2nd]test 步骤 根据题目,ssh连接一下靶机 登录成功后,ls看一下当前目录下的文件,根据提示可知,我们没法直接获取flag字符串,但是我们可以读取test的源码, test. ...

  10. 工作簿合并(Excel代码集团)

    同一文件夹内N个工作簿 ,每个工作簿里N个工作表,最终合并到一个工作表里的代码. 假设每个表格结构相同,第一行为标题,第二行为表头,表头内容固定,行数不固定,列固定14,工作表数量不固定,工作簿数量不 ...