题目链接: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. Android -- 启动另外一个Activity的方式(2s自动启动)

    1.  使用Handler  并且可以设置进入和退出的动画效果 Class < ? > activityClass; Class [ ] paramTypes = { Integer.TY ...

  2. JS运算符

    JS运算符: 使用的运算符的时候不需要声明变量,运算符非变量:1.算术运算符 + - * / % (%为取余数运算符) (自增运算符++) (自减运算符 --) + 运算符作用:1.数值相加 2.字符 ...

  3. Mysql5.7修改默认密码

    由于 Mysql5.7的默认密码是随机生成的,所以需要修改成我们自己常用的密码 1.修改 my.ini,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 my ...

  4. php上传大文件时,服务器端php.ini文件中需要额外修改的选项

    几个修改点: 1.upload_max_filesize 上传的最大文件 2.post_max_size 上传的最大文件 3.max_execution_time 修改为0表示无超时,一直等待 4.m ...

  5. presto-elasticsearch connector

    elasticsearch搜索功能强劲,就是查询语法复杂,presto提供了非常open的plugin机制,我改进了下原有的presto-elasticsearch connector,现发布于git ...

  6. Shell 重定向

    一直没搞懂 &> 和 <& 是表示什么意思. 今天自己总结一下,希望自己能理解它的真正含义. 重定向标准输入输出,切记 “1” 和 “>”之间没有空格 $ > ...

  7. django--models操作

    1.models的功能 操作数据库 提交验证 在django的admin中,使用的是modelForms所以在验证的时候,尽管在models后有error_ message参数也不会根据此来提示.具体 ...

  8. idea使用心得(2)-安装设置与创建web项目

    idea 是与eclipse齐名的IDE(集成开发工具),以智能闻名,不过对于熟悉eclipse的的用户来说,初次接触idea有些让人搞不清方向,下面介绍一下简单的使用 方式. 1.安装 官网下载ul ...

  9. orange pi pc 体验(二)远程登录服务器

    1.本人的板子是orangepi  pc,安装的debian系统 2.启动完成后,默认可以用xshell登录板子的,使用nano更改/etc/apt/source.list root@OrangePI ...

  10. imx6 matrix keyboard

    imx6需要添加4x4的矩阵键盘.本文记录添加方法. 参考链接 http://processors.wiki.ti.com/index.php/TI-Android-JB-PortingGuide h ...