【问题描述】

有一颗n个节点的树

每个节点上都有许多奸商在卖东西,第i个奸商的理想价格为vi,即他会以vi的价格购买或卖出一件东西

有m个人希望从树上的某个点走到另一个点,问你在只进行一次买卖(每次仅限一个商品)的情况下,每个人最多能赚多少钱

【输入】

输入第一行是一个整数 n,表示树上的点数。

接下来n个正整数,表示每个奸商的理想价格。

接下来n-1行,每行两个整数x,y,表示第x点和第y点有一条边。

接下来一个整数m,表示下来有m个询问。

接下来有m行,每行两个整数x和y,表示某个人要从第x点出发到第y点。

【输出】

输出包括m行。

每行对应一个询问,一个整数,表示此人最多能赚到多少钱。

【输入输出样例1】

10

3 4 1 2 7 6 1 5 3 9

1 2

1 9

3 1

9 7

5 9

6 9

8 7

4 7

10 7

3

5 6

8 10

2 4

3

8

1

【数据范围】

对于前40%数据 n<=1000, m<=1000

对于100%数据 n<=250000 ,m<=10000

t1
离线lca+dp思想

先说一说题外话,我后来看我自己的代码时,我看了差不多半天,也没有看懂。

最后总算是理解了代码的思想。

我们假设一个中间节点z
一件商品,假设u和v的lca是z
那么对于一次买卖,有三种情况:
一件商品,我们在u,f之间买卖了,在u,f之间买了,在f,v之间卖了,在f,v之间买卖了
接着我们想,对于三种情况,基于贪心的思想,必然是这样几种情况:
1.在u,f间价格最小的地方买入,在u,f间价格最大的地方卖出,
2.在u,f间价格最小的地方买入,在f,v间价格最大的地方卖出
3.在f,v间价格最小的地方买入,在f,v间价格最大的地方卖出
也就是说,我们要维护4个量:
u,f间的最大和最小值,f,v间的最大和最小值
从u到f 我们称为up, 从f到v我们称为down,而从u到f买然后在f到v卖就是求u到f的最小值和f到v的最大值

先求出u,v的最近公共祖先f
再求出u到f再到v的最大利润值maxval
这个maxval有三种情况
1.可能是u到f的利润最大值
2.可能是f到v的利润最大值
3.可能是f到v的最大w[i] - u到f的最小w[i]
这样就是说,我们需要4个变量才能得到最终的利润最大值
up[u]表示u到f的利润最大值
down[v]表示f到v的利润最大值
maxw[u]表示u到f的最大w[i]
minw[u]表示u到f的最小w[i]

首先,我们可以知道的是,原来我们暴力写肯定就是先求出LCA,然后再从u和v到lca更新重新更新

所以我们的优化思路是在求LCA的同时对4个值进行更新

那么我接下来就要解决这个问题了,我们显然可以用到一些DP的思想,

我们上面已经开了4个数组

up[u]表示u到f的利润最大值
down[v]表示f到v的利润最大值
maxw[u]表示u到f的最大w[i]
minw[u]表示u到f的最小w[i]

然后我们在利用并查集路径压缩的同时更新这些值,现在我们要解决的是,如何能按照求lca的次序,同时回答询问

这就是说我们要给询问排一个序号,按照求lca得顺序完成询问,然后通过序号,把答案确定在答案数组的正确位置。

对于每个点, 我们进行dfs的时候,查看与其相关的询问,

假设当前点是u, 询问的点是v, u和v的LCA是f,如果v已经dfs过了,说明v在并查集中的祖先就是u,v的LCA  f点,

将该询问加入到f的相关集合中,等f所有的子节点都处理过后再去处理f, 就可以发现,一切都是顺其自然了

在这些处理过程中,up和down以及u,v到f的最大值最小值  都可以在并查集求压缩路径的过程中更新。

同时我们注意到,

 #include<bits/stdc++.h>
using namespace std;
const int maxn = ;
const int maxm = ;
struct kkk {
int net, y, id;
}ef[maxn << ], es[maxn << ], et[maxn << ];
int linf[maxn], lenf = ;
int lins[maxn], lens = ;
int lint[maxn], lent = ;
int n, m, w[maxn];
int fa[maxn], u[maxm], v[maxm];
int up[maxn], down[maxn];
int maxw[maxn], minw[maxn];
int ans[maxn];
int vis[maxn]; inline int read() {
int x = , y = ;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') y = -;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << ) + (x << ) + ch - '';
ch = getchar();
}
return x * y;
} inline void insert_f(int xx, int yy, int id) {
ef[++lenf].net = linf[xx];
ef[lenf].id = id;
ef[lenf].y = yy;
linf[xx] = lenf;
} inline void insert_s(int xx, int yy, int id) {
es[++lens].id = id;
es[lens].net = lins[xx];
es[lens].y = yy;
lins[xx] = lens;
} inline void insert_t(int xx, int yy, int id) {
et[++lent].id = id;
et[lent].net = lint[xx];
et[lent].y = yy;
lint[xx] = lent;
} inline int getfather(int x) {
if(x == fa[x]) return x;
int f = fa[x];
fa[x] = getfather(fa[x]);
up[x] = max(max(up[x], up[f]), maxw[f] - minw[x]);
down[x] = max(max(down[x], down[f]), maxw[x] - minw[f]);
maxw[x] = max(maxw[x], maxw[f]);
minw[x] = min(minw[x], minw[f]);
return fa[x];
} inline void LCA(int x) {//x表示的是公共祖先
vis[x] = ;
fa[x] = x;
for(int i = lins[x]; i; i = es[i].net) {
int to = es[i].y, id = es[i].id;
if(!vis[to]) continue;
int dad = getfather(to);
insert_t(dad, x, id);
}
for(int i = linf[x]; i; i = ef[i].net) {
int to = ef[i].y;
if(vis[to]) continue;
LCA(to);
fa[to] = x;//把to的父亲标记为他的父亲
}
for(int i = lint[x]; i; i = et[i].net) {//在父亲节点x处理所有的关于他的子节点的询问
int id = et[i].id;
getfather(u[id]);
getfather(v[id]);
ans[id] = max(max(up[u[id]], down[v[id]]), maxw[v[id]] - minw[u[id]]);
}
} int main() {
// freopen("gift.in", "r", stdin);
// freopen("gift.out", "w", stdout);
n = read();
for(int i = ; i <= n; ++i) {
w[i] = read();
up[i] = down[i] = ;
maxw[i] = minw[i] = w[i];
}
for(int i = ; i < n; ++i) {
int x, y;
x = read(), y = read();
insert_f(x, y, i);
insert_f(y, x, i);
}
m = read();
for(int i = ; i <= m; ++i) {
u[i] = read(), v[i] = read();
insert_s(u[i], v[i], i);
insert_s(v[i], u[i], i);
}
LCA();
for(int i = ; i <= m; ++i) {
if(ans[i] < ) cout << << '\n';
else cout << ans[i] << '\n';
}
// fclose(stdin);
// fclose(stdout);
return ;
}

但是此代码并不能A掉Poj原题,因为,数据范围不一样

集训day15 t1 poj3728的更多相关文章

  1. FJ省队集训DAY3 T1

    思路:我们考虑如果取掉一个部分,那么能影响到最优解的只有离它最近的那两个部分. 因此我们考虑堆维护最小的部分,离散化离散掉区间,然后用线段树维护区间有没有雪,最后用平衡树在线段的左右端点上面维护最小的 ...

  2. Yali7月集训Contest2 T1 Cube 题解

    题目链接: 连我们都只有纸质题目...话说雅礼集训都是这样的吗... 大意 0维基本图形是一个点 1维基本图形是一条线段 2维基本图形是一个正方形 3维基本图形是一个正方体 4维基本图形是... 求\ ...

  3. FJ省队集训DAY5 T1

    思路:考试的时候打了LCT,自以为能过,没想到只能过80.. 考完一想:lct的做法点数是100W,就算是nlogn也会T. 讲一下lct的做法把:首先如果一条边连接的两个点都在同一个联通块内,那么这 ...

  4. FJ省队集训DAY4 T1

    直接上题解 #include<cstdio> #include<iostream> #include<cmath> #include<cstring> ...

  5. FJ省队集训DAY2 T1

    思路:转换成n条三维空间的直线,求最大的集合使得两两有交点. 有两种情况:第一种是以某2条直线为平面,这时候只要统计这个平面上有几条斜率不同的直线就可以了 还有一种是全部交于同一点,这个也只要判断就可 ...

  6. FJ省队集训DAY1 T1

    题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆. 思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会 ...

  7. 雅礼集训 Day7 T1 Equation 解题报告

    Reverse 题目背景 小\(\text{G}\)有一个长度为\(n\)的\(01\)串\(T\),其中只有\(T_S=1\),其余位置都是\(0\).现在小\(\text{G}\)可以进行若干次以 ...

  8. 雅礼集训 Day6 T1 Merchant 解题报告

    Merchant 题目描述 有\(n\)个物品,第\(i\)个物品有两个属性\(k_i,b_i\),表示它在时刻\(x\)的价值为\(k_i\times x+b_i\). 当前处于时刻\(0\),你可 ...

  9. 雅礼集训 Day1 T1 养花

    养花 题目描述 小\(C\)在家种了\(n\)盆花,每盆花有一个艳丽度\(a_i\). 在接下来的\(m\)天中,每天早晨他会从一段编号连续的花中选择一盆摆放在客厅, 并在晚上放回. 同时每天有特定的 ...

随机推荐

  1. jQuery.getJSON跨域访问的正确使用方式(史上最傻瓜式解释)

    最近花了2天时间完整的看了一遍 jQuery 的API,其中 $.getJSON(url[, data][, callback]) 方法的跨域访问解释真心看的一头雾水,大家可以从这里感受一下: htt ...

  2. yum命令Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY

    yum命令Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY 博客分类: linux   三种解决方案 我采取第三种方案解决的 第一种: linu ...

  3. [fzu 2282]置换不动点大于等于k的排列数

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=2282 编号1~n的置换,不动点个数大于等于k的方案数. 参考百度百科错排公式,可以知道长度为n,每个数都不在自 ...

  4. HDU4370:0 or 1(最短路)

    0 or 1 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4370 Description: Given a n*n matrix Cij (1< ...

  5. 如何解决DuplicateFileException: Duplicate files copied in APK问题

    问题:有重复的文件存在APK里 解决方案:在Module里的build.gradle中设置忽略此重复文件即可.

  6. 图片和base64编码字符串 互相转换,图片和byte数组互相转换

    图片和base64编码字符串 互相转换 import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import java.io.*; ...

  7. classList详解,让你的js方便地操作DOM类

    在此之前,jQuery的hasClass.addClass.removeClass我们已经再熟悉不过了,然而我们并不会在每一个项目中都会去使用 jQuery或者Zepto,譬如在移动端的网页中,考虑到 ...

  8. HDU1232 畅通工程---(经典并查集应用)

    http://acm.hdu.edu.cn/showproblem.php?pid=1232 畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory ...

  9. 【sgu390】数位dp

    这题其实就是不断地合并子树,跟前面例一的思想是一样的. 这个打法我觉得非常优美啊(学别人的),为什么要搞lim1和lim2呢? 是因为在区间lim1~lim2之外的都是没有用的,但是我们f[h][su ...

  10. python Fielddata is disabled on text fields

    # 执行https://www.elastic.co/guide/cn/elasticsearch/guide/current/_aggregation_test_drive.html中的例子时报错F ...