集训day15 t1 poj3728
【问题描述】
有一颗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的更多相关文章
- FJ省队集训DAY3 T1
思路:我们考虑如果取掉一个部分,那么能影响到最优解的只有离它最近的那两个部分. 因此我们考虑堆维护最小的部分,离散化离散掉区间,然后用线段树维护区间有没有雪,最后用平衡树在线段的左右端点上面维护最小的 ...
- Yali7月集训Contest2 T1 Cube 题解
题目链接: 连我们都只有纸质题目...话说雅礼集训都是这样的吗... 大意 0维基本图形是一个点 1维基本图形是一条线段 2维基本图形是一个正方形 3维基本图形是一个正方体 4维基本图形是... 求\ ...
- FJ省队集训DAY5 T1
思路:考试的时候打了LCT,自以为能过,没想到只能过80.. 考完一想:lct的做法点数是100W,就算是nlogn也会T. 讲一下lct的做法把:首先如果一条边连接的两个点都在同一个联通块内,那么这 ...
- FJ省队集训DAY4 T1
直接上题解 #include<cstdio> #include<iostream> #include<cmath> #include<cstring> ...
- FJ省队集训DAY2 T1
思路:转换成n条三维空间的直线,求最大的集合使得两两有交点. 有两种情况:第一种是以某2条直线为平面,这时候只要统计这个平面上有几条斜率不同的直线就可以了 还有一种是全部交于同一点,这个也只要判断就可 ...
- FJ省队集训DAY1 T1
题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆. 思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会 ...
- 雅礼集训 Day7 T1 Equation 解题报告
Reverse 题目背景 小\(\text{G}\)有一个长度为\(n\)的\(01\)串\(T\),其中只有\(T_S=1\),其余位置都是\(0\).现在小\(\text{G}\)可以进行若干次以 ...
- 雅礼集训 Day6 T1 Merchant 解题报告
Merchant 题目描述 有\(n\)个物品,第\(i\)个物品有两个属性\(k_i,b_i\),表示它在时刻\(x\)的价值为\(k_i\times x+b_i\). 当前处于时刻\(0\),你可 ...
- 雅礼集训 Day1 T1 养花
养花 题目描述 小\(C\)在家种了\(n\)盆花,每盆花有一个艳丽度\(a_i\). 在接下来的\(m\)天中,每天早晨他会从一段编号连续的花中选择一盆摆放在客厅, 并在晚上放回. 同时每天有特定的 ...
随机推荐
- 在VS2012中设置默认启动
Visual Studio 2012一个解决方案中多个项目,如果想选择哪个项目就设置哪个项目为启动项就好了. 第一种方法,工具===〉〉选项===〉〉〉项目解决方案===〉〉〉对于新的解决方案,使用单 ...
- bzoj1726 第二短路
一道严格次短路题,WA了一下午回家才发现bellman_ford中的vis [ o ] = false 写成了 vis [ S ] = false.被自己脑残了一脸.... #include<c ...
- IPVS和Nginx两种WRR负载均衡算法详解
动机 五一临近,四月也接近尾声,五一节乃小长假的最后一天.今天是最后一天工作日,竟然感冒了,半夜里翻来覆去无法安睡,加上窗外大飞机屋里小飞机(也就是蚊子)的骚扰,实在是必须起来做点有意义的事了! ...
- 停课day5
一转眼,已经停课五天了. 高二大佬们已经都走了,在机房里面呆着,有时感觉很孤寂. 但是为了能学好竞赛,这些都是在所不惜的. 好像多打打比赛啊,可是cf要FQ,洛谷之类的比赛还不勤. 哎,先去学一发SP ...
- CodeForces743E. Vladik and cards 二分+状压dp
这个题我们可以想象成_---___-----__的一个水柱它具有一遍优一遍行的性质因此可以用来二分最小值len,而每次二分后我们都要验根,we可以把这个水柱想成我们在每个数段里取前一段的那个数后一段有 ...
- 常见编程语言对REPL支持情况小结
最近跟一个朋友聊起编程语言的一些特性,他有个言论让我略有所思:“不能REPL的都是渣”.当然这个观点有点偏激,但我们可以探究一下,我们常用的编程语言里面,哪些支持REPL,哪些不支持,还有REPL的一 ...
- Mockito中@Mock与@InjectMock
Mockito是java单元测试中,最常用的mck工具之一,提供了诸多打桩方法和注解.其中有两个比较常用的注解,@Mock和@InjectMock,名字和在代码中使用 的位置都很像,对于初学者,很容易 ...
- 获取html元素内容
html: <!DOCTYPE ><html> <head> <meta http-equiv="Content-Type" conten ...
- Sencha Touch2 -- 11.1:定义具有关联关系的模型
在Sencha Touch2.0中,可以定义不同模型之间的关联关系.例如,在开发博客网站的时候,可以首先定义用户(User)模型,然后为用户定义文章(Article)模型.一个用户可以发表多篇文章,因 ...
- hdu 1509 Windows Message Queue (优先队列)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1509 题目大意:每一次输入都有序号和优先级,优先级小的先输出,优先级相同的话则序号小的先输出!第一次用 ...