UVALive 7148 LRIP(树的分治+STL)(2014 Asia Shanghai Regional Contest)
题目链接: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)的更多相关文章
- UVALive 7141 BombX(离散化+线段树)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
- 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. ...
- 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 ...
- UVALive 7143 Room Assignment(组合数学+DP)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
- UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
- UVALive 7139 Rotation(矩阵前缀和)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
- hdu5071 2014 Asia AnShan Regional Contest B Chat
模拟题: add的时候出现过的则不再添加 close的时候会影响到top rotate(Prior.Choose)的时候会影响到top /*============================== ...
- 2014 Asia AnShan Regional Contest --- HDU 5073 Galaxy
Galaxy Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5073 Mean: 在一条数轴上,有n颗卫星,现在你可以改变k颗 ...
- 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),现在要从 ...
随机推荐
- C# 正则表达式
引用自:http://www.cnblogs.com/stg609/archive/2009/06/03/1492709.html 摘要:正则表达式(Regular Expressions),相信做软 ...
- table首行固定
转自http://www.cnblogs.com/azhqiang/p/3965774.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. ...
- STM32之SRAM调试
在学习STM32的时候,由于烧FLASH的所造成的时间会比较慢,而在SRAM中调试的时间会比FLASH快很多,再加上FLASH的时候会经常擦除芯片,会对芯片的寿命造成一定的影响, 其实我本人觉得在学习 ...
- jQuery的封装方式与JS中new的实现原理
function jQuery() { return new jQuery.fn.init(); } jQuery.fn = jQuery.prototype = { init: function() ...
- linux中test与[ ]指令的作用
linux中test与[ ]指令的作用: 在Linux中,test和[ ]功能是一样的,类似于c语言中的( ).不过Linux的test和[ ]是指令.在和if或者while联用时要用空格分开.
- source insight使用
左键选中后 ctrl+ 跳转到定义 alt+,返回到调用者的程序
- harris角点检测的学习
Harris通过运用微分运算和自相关矩阵改进了Moravec角点检测算法.用微分算子重新定义灰度强度变化的公式,其灰度强度变化表示为: 式中的wu,v为高斯窗口在(u,v)处的系数.X,Y它们是像素点 ...
- php实现网页trace方法
// 记录内存初始使用和开始时间,在系统的入口记录 $beginTime= microtime(TRUE); $start_memory = memory_get_usage(); //die; ec ...
- TiD大会学习心得之沟通交流
沟通交流是敏捷成功的关键要素,据相关调查阻碍敏捷的主要原因都与人有关:例如缺乏领导支持.团队缺乏协作精神.公司文化与敏捷相冲突等等:同时沟通交流也是团队建设.教练自身成长的重要支柱.下面结合在< ...
- Qt之创建桌面和开始菜单快捷方式
将安装好的酷狗拷贝到C:\data目录中 1.创建桌面快捷方式 QFile::link("C:/data/KuGou.exe", QStandardPaths::writableL ...