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),现在要从 ...
随机推荐
- Python for Informatics 第11章 正则表达式五(译)
注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 11.4 转义字符 之前我们在正 ...
- Bugtags 测试平台(支持ios、android)
官网:https://bugtags.com/ 注意:小米手机 授权 打开漂浮窗 App 集成 Bugtags SDK 后,测试人员就可直接在 App 里所见即所得的提交 Bug; SDK 会自动截屏 ...
- .NET面试题目
简单介绍下ADO.NET和ADO主要有什么改进? 答:ADO以Recordset存储,而ADO.NET则以DataSet表示,ADO.NET提供了数据集和数据适配器,有利于实现分布式处理,降低了对数据 ...
- js的三种继承方式及其优缺点
[转] 第一种,prototype的方式: //父类 function person(){ this.hair = 'black'; this.eye = 'black'; this.skin = ' ...
- 【转】【Raspberry Pi】Unix NetWork Programming:配置unp.h头文件环境
一.初衷 近期正在做网络计算编程的作业.要求平台为unix/linux,想着Raspberry Pi装的Debian系统也是Linux改的,也应该能够勉强用着,所以就用它来做作业了! 二.说明 先把环 ...
- 【转】WiFi基础知识
http://blog.csdn.net/myarrow/article/details/7930131 1. IE802.11简介 标准号 IEEE 802.11b IEEE 802.11a IEE ...
- linux文件数相关命令
查看系统目前打开的文件数命令#cat /proc/slabinfo | grep ip_conn | grep -v ip_conntrack_expect | awk '{print $2}' 查看 ...
- Oracle知识分类之异常
Oracle异常分类 ...
- ORM系列之二:EF(4) 约定、注释、Fluent API
目录 1.前言 2.约定 2.1 主键约定 2.2 关系约定 2.3 复杂类型约定 3.数据注释 3.1 主键 3.2 必需 3.3 MaxLength和MinLength 3.4 NotMapped ...
- 网络监测工具-iftop教程
在类Unix系统中可以使用top查看系统资源.进程.内存占用等信息.查看网络状态可以使用netstat.nmap等工具.若要查看实时的网络流量,监控TCP/IP连接等,则可以使用iftop. 一.if ...