题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=648&page=show_problem&problem=5160

There is a tree with N nodes, and every node has a weighted value. A RIP (restricted increasing path)
is a directed path with all nodes’ weighted values not decreasing and the difference between the max
weighted value and the min weighted value is not larger than D. Find the length of longest restricted
increasing path (LRIP).
A path in a tree is a finite or in finite sequence of edges which connect a sequence of vertices which
are all distinct from one another. A directed path is again a sequence of edges which connect a sequence
of vertices, but with the added restriction that the edges all be directed in the same direction.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts
with two integers N and D, which indicates the number of nodes in the tree and the restricted value.
The following line contains N integers, a1, a2, …, ai
, …, aN , which indicates the i-th node’s weighted
value. Then N − 1 lines follow, every line contains two integers u, v (1 ≤ u, v ≤ N), which means there
is a path between u-th node and v-th node.
Output
For each test case, output one line containing ‘Case #x: y’, where x is the test case number (starting
from 1) and y is the length of LRIP of this tree.
Unofficial clarification: The last N −1 lines for each testcase describe edges, not paths. These edges
are undirected (i.e. you can make it a directed edge in either direction), and the length of a path is the
number of nodes on it.
Limits:
1 ≤ T ≤ 10
1 ≤ ai ≤ 10^5
, 1 ≤ i ≤ N
1 ≤ N, D ≤ 10^5

题目大意:给一棵带点权的树,求树上的一条最长不下降路径,使得最大结点和最小结点的差不超过一个给定的D。

思路:其实直接遍历+启发式合并大概也可以做,但是用树的点分治要容易地多……

首先,对于每次分治,找到一个分治中心root,寻找“所有”经过root的路径,并把root删去,继续分治。

那么,如何找到经过root的路径呢?

假设root的儿子为list(son),依次遍历每个儿子,并维护上升路径的集合,再从所有下降路径中寻找最佳的上升路径。

维护的集合为上升路径的权值+上升路径的深度(假设根为root)。

若上升路径的序列中,权值严格递增,深度严格递减(舍弃多余的路径),那么下降路径寻找最佳上升路径的时候,直接二分即可。

至于维护上面说的集合,可以使用线段树来维护,也可以使用std::map来维护(考验STL水平的时候到了)。

总复杂度为O(n(logn)^2)。

PS:什么是多余的上升路径?设权值为val,深度为dep。若val[u]≥val[v]且dep[u]≥dep[v],那么v在任意时刻都不会比u更优,可以舍弃。因为我们要找的是权值大于等于某个值的深度最大的结点。

代码(0.736S):

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
typedef long long LL; const int MAXV = ;
const int MAXE = MAXV * ; int head[MAXV], val[MAXV], ecnt;
int to[MAXE], nxt[MAXE];
int n, D, T, res; void init() {
memset(head + , -, n * sizeof(int));
ecnt = ;
} void add_edge(int u, int v) {
to[ecnt] = v; nxt[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; nxt[ecnt] = head[v]; head[v] = ecnt++;
} int size[MAXV], maxBranch[MAXV];
bool del[MAXV];
vector<int> nodes; void dfs_size(int u, int f) {
size[u] = ;
maxBranch[u] = ;
for(int p = head[u]; ~p; p = nxt[p]) {
int v = to[p];
if(del[v] || v == f) continue;
dfs_size(v, u);
size[u] += size[v];
maxBranch[u] = max(maxBranch[u], size[v]);
}
nodes.push_back(u);
}
int get_root(int u) {
nodes.clear();
dfs_size(u, -);
int rt = u;
for(int v : nodes) {
maxBranch[v] = max(maxBranch[v], size[u] - size[v]);
if(maxBranch[v] < maxBranch[rt]) rt = v;
}
return rt;
} map<int, int> up; void insert(int val, int len) {
auto x = up.lower_bound(val);
if(x != up.end() && x->second >= len) return ; auto ed = up.upper_bound(val);
//printf("#debug %d %d\n", ed->first, ed->second);
auto it = map<int, int>::reverse_iterator(ed);
while(it != up.rend() && it->second <= len) ++it;
up.erase(it.base(), ed);
up[val] = len;
} void dfs_up(int u, int f, int dep) {
insert(val[u], dep);
for(int p = head[u]; ~p; p = nxt[p]) {
int v = to[p];
if(!del[v] && v != f && val[v] <= val[u])
dfs_up(v, u, dep + );
}
} void dfs_down(int u, int f, int dep) {
auto it = up.lower_bound(val[u] - D);
if(it != up.end()) res = max(res, it->second + dep + );
for(int p = head[u]; ~p; p = nxt[p]) {
int v = to[p];
if(!del[v] && v != f && val[v] >= val[u])
dfs_down(v, u, dep + );
}
} void _work(int u, vector<int> &son) {
up.clear();
up[val[u]] = ;
for(int v : son) {
if(val[v] >= val[u]) dfs_down(v, u, );
if(val[v] <= val[u]) dfs_up(v, u, );
}
}
void work(int rt) {
vector<int> son;
for(int p = head[rt]; ~p; p = nxt[p])
if(!del[to[p]]) son.push_back(to[p]); _work(rt, son);
reverse(son.begin(), son.end());
_work(rt, son);
} void solve(int st) {
int u = get_root(st);
work(u); del[u] = true;
for(int p = head[u]; ~p; p = nxt[p]) {
int v = to[p];
if(!del[v]) solve(v);
}
} int main() {
scanf("%d", &T);
for(int t = ; t <= T; ++t) {
scanf("%d%d", &n, &D);
init();
for(int i = ; i <= n; ++i) scanf("%d", &val[i]);
for(int i = , u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
add_edge(u, v);
} memset(del + , , n * sizeof(bool));
res = ;
solve();
printf("Case #%d: %d\n", t, res);
}
}

小插曲:AC过两天居然改数据rejudge了!然而发现机房居然各种不能上网。用爪机看了看代码,大概就少了处理n=1的情况。后来能上网后随手交交就AC了。其他题似乎也rejudge了o(╯□╰)o,还好我平时写完代码都有自己保存,不然就坑爹了。

UVALive 7148 LRIP(树的分治+STL)(2014 Asia Shanghai Regional Contest)的更多相关文章

  1. UVALive 7141 BombX(离散化+线段树)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  2. UVALive 7146 Defeat the Enemy(贪心+STL)(2014 Asia Shanghai Regional Contest)

    Long long ago there is a strong tribe living on the earth. They always have wars and eonquer others. ...

  3. UVALive 7138 The Matrix Revolutions(Matrix-Tree + 高斯消元)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  4. UVALive 7143 Room Assignment(组合数学+DP)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  5. UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  6. UVALive 7139 Rotation(矩阵前缀和)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  7. hdu5071 2014 Asia AnShan Regional Contest B Chat

    模拟题: add的时候出现过的则不再添加 close的时候会影响到top rotate(Prior.Choose)的时候会影响到top /*============================== ...

  8. 2014 Asia AnShan Regional Contest --- HDU 5073 Galaxy

    Galaxy Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5073 Mean: 在一条数轴上,有n颗卫星,现在你可以改变k颗 ...

  9. dp --- 2014 Asia AnShan Regional Contest --- HDU 5074 Hatsune Miku

    Hatsune Miku Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5074 Mean: 有m种音符(note),现在要从 ...

随机推荐

  1. 【原】iOS学习之应用程序的启动原理

    最近看视频了解了一下应用程序的启动原理,这里就做一个博客和大家分享一下,相互讨论,如果有什么补充或不同的意见可以提出来! 1.程序入口 众所周知,一个应用程序的入口一般是一个 main 函数,iOS也 ...

  2. javascript面向对象(一):封装

    本文来自阮一峰 学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握. 下面就是我的学 ...

  3. webform 复合控件

    RadioButtonList  单选按钮列表 属性:RepeatColumns 用于布局项的列数(每一行的个数) RepeatDirection 选择Vertical,纵向排列:选择Horizont ...

  4. Odoo 8.0 new API 之Environment

    """ An environment wraps data for ORM records: - :attr:`cr`, the current database cur ...

  5. log4j详解(二)

    在实际编程时,要使Log4j真正在系统中运行事先还要对配置文件进行定义.定义步骤就是对Logger.Appender及Layout的分别使用.Log4j支持两种配置文件格式,一种是XML格式的文件,一 ...

  6. RAC初体验

    什么是RAC? 几乎每一篇介绍RAC的文章开头都是这么一个问题.我这篇文章是写给新手(包括我自己)看的,所以这个问题更是无法忽视. 简单的说,RAC就是一个第三方库,他可以大大简化你的代码过程. 官方 ...

  7. Lua系统库

    Lua为了保证高度的可移植性,因此,它的标准库仅仅提供了非常少的功能,特别是和OS相关的库.但是Lua还提供了一些扩展库,比如Posix库等.对于文件操作而言,该库仅提供了os.rename函数和os ...

  8. dblink嵌套场景下 查询出现:ORACLE ORA-00600错误的解决

    前段时间在做oracle查询的时候遇到了一个非常奇怪的现象,现将现象和解决过程记录下来,以备查看: 环境描述:A数据库通过dblink访问B数据库的视图,B数据库的视图的数据是通过B的dblink连接 ...

  9. java面向对象_抽象类和接口

    一.抽象类 1.抽象方法:由abstract修饰.只有定义没有方法体.用一个分号结尾. 2.抽象类: 1)包含抽象方法的类必须是抽象类 2)由abstract修饰 3)不能被实例化 4)抽象类如果不被 ...

  10. EMF学习,为了实现可扩展可自定义的模型验证 - emf quary 与 OCL

    http://blog.csdn.net/javaman_chen/article/details/6020050 //这里的验证强调的是condition的构造,基于查找来判断验证结果.支持OCL也 ...