UVALive 7148 LRIP 14年上海区域赛K题 树分治
2015-11-27 23:27
387 查看
题意 n个点组成一棵树, 带有点权。 求最长不降的路径的长度, 且路径上最大值最小值之差不超过D。
显然是树分治, 但是分治之后如何维护答案呢。
假设当前重心为g, 分别记录g出发不降路径的长度,以及最大值, 和不升路径的长度以及最小值。
这里用到一个map和二分, 线段树也可以, 但是如果用线段树还要考虑负值, 再加上线段树的clear以及稍微暴力的查询。 常数大小不好说。
显然是树分治, 但是分治之后如何维护答案呢。
假设当前重心为g, 分别记录g出发不降路径的长度,以及最大值, 和不升路径的长度以及最小值。
这里用到一个map和二分, 线段树也可以, 但是如果用线段树还要考虑负值, 再加上线段树的clear以及稍微暴力的查询。 常数大小不好说。
#include <bits/stdc++.h> using namespace std; typedef pair <int, int> pii; const int maxn = 1e5 + 5; vector <int> G[maxn]; int val[maxn], siz[maxn], n, D; bool centroid[maxn]; void init() { for (int i = 0; i < maxn; i++) { G[i].clear(); } memset(centroid, false, sizeof centroid); } void dfs(int u, int father){ siz[u] = 1; for (int v: G[u]){ if (v != father && !centroid[v]){ dfs(v, u); siz[u] += siz[v]; } } } pii FindCentroid(int u, int father, int t) { pii res = make_pair(INT_MAX, -1); int s = 1, m = 0; for (int v: G[u]) { if (v == father || centroid[v]) { continue; } res = min(res, FindCentroid(v, u, t)); m = max(m, siz[v]); s += siz[v]; } siz[u] = s; m = max(m, t-s); return min(res, make_pair(m, u)); } map <int, int> work; void update(int v, int len) { auto it = work.lower_bound(v); if (it != work.end() && it->second >= len) { return; } work[v] = len; } void dfs_up(int u, int father, int d) { if (val[u] > val[father]) { return; } update(val[u], d); for (int v: G[u]) { if (v != father && !centroid[v]) { dfs_up(v, u, d+1); } } } int res; void dfs_down(int u, int father, int d) { if (val[u] < val[father]) { return; } auto it = work.lower_bound(val[u]-D); if (it != work.end()) { res = max(res, it->second+1+d); } for (int v: G[u]) { if (!centroid[v] && v != father) { dfs_down(v, u, d+1); } } } void preSolve(int g, vector <int> &son) { work.clear(); work[val[g]] = 0; for (int v: son) { if (val[v] >= val[g]) { dfs_down(v, g, 1); } if (val[v] <= val[g]) { dfs_up(v, g, 1); } } } void solve(int u) { dfs(u, 0); int g = FindCentroid(u, 0, siz[u]).second; vector <int> son; for (int v: G[g]) { if (!centroid[v]) { son.push_back(v); } } preSolve(g, son); reverse(son.begin(), son.end()); preSolve(g, son); centroid[g] = true; for (int v: G[g]) { if (!centroid[v]) { solve(v); } } } int main() { // freopen("in.txt", "r", stdin); int T, cas = 1; scanf ("%d", &T); while (T--) { init(); scanf ("%d%d", &n, &D); for (int i = 1; i <= n; i++) { scanf ("%d", val+i); } for (int i = 1; i < n; i++) { int u, v; scanf ("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } res = 1; solve(1); printf("Case #%d: %d\n", cas++, res); } return 0; }
相关文章推荐
- 画饼图
- TinyOS论文04:Demo: Towards Bug-free Implementation for Wireless Sensor Networks
- oracle 基础1
- 森林病虫防治系统 (七)
- 南大软院大神养成计划--js
- quzed2D进度条
- 多种方法实现Excel批量导入数据库
- 欢迎使用CSDN-markdown编辑器
- nyoj+区间dp括号匹配
- 温故知新—Java8复习之始
- UITabBarController使用详解
- sicily 1205. brainf*ck
- Swift语言计算属性简单理解
- 程序的环境
- pushd popd shift ATTRIB
- CALayer的使用
- new和malloc的区别
- 加油!
- UINavigationController使用详解
- Windows/DOS与Unix文件格式之间的相互转换(/r/n问题)