UVALive 7148 LRIP 14年上海区域赛K题 树分治

题意 n个点组成一棵树, 带有点权。 求最长不降的路径的长度, 且路径上最大值最小值之差不超过D。

显然是树分治, 但是分治之后如何维护答案呢。

假设当前重心为g, 分别记录g出发不降路径的长度,以及最大值, 和不升路径的长度以及最小值。

这里用到一个map和二分, 线段树也可以, 但是如果用线段树还要考虑负值, 再加上线段树的clear以及稍微暴力的查询。  常数大小不好说。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef pair <int, int> pii;
  4 const int maxn = 1e5 + 5;
  5 vector <int> G[maxn];
  6 int val[maxn], siz[maxn], n, D;
  7 bool centroid[maxn];
  8 void init() {
  9     for (int i = 0; i < maxn; i++) {
 10         G[i].clear();
 11     }
 12     memset(centroid, false, sizeof centroid);
 13 }
 14 void dfs(int u, int father){
 15     siz[u] = 1;
 16     for (int v: G[u]){
 17         if (v != father && !centroid[v]){
 18             dfs(v, u);
 19             siz[u] += siz[v];
 20         }
 21     }
 22 }
 23 pii FindCentroid(int u, int father, int t) {
 24     pii res = make_pair(INT_MAX, -1);
 25     int s = 1, m  = 0;
 26     for (int v: G[u]) {
 27         if (v == father || centroid[v]) {
 28             continue;
 29         }
 30         res = min(res, FindCentroid(v, u, t));
 31         m = max(m, siz[v]);
 32         s += siz[v];
 33     }
 34     siz[u] = s;
 35     m = max(m, t-s);
 36     return min(res, make_pair(m, u));
 37 }
 38 map <int, int> work;
 39 void update(int v, int len) {
 40     auto it = work.lower_bound(v);
 41     if (it != work.end() && it->second >= len) {
 42         return;
 43     }
 44     work[v] = len;
 45 }
 46 void dfs_up(int u, int father, int d) {
 47     if (val[u] > val[father]) {
 48         return;
 49     }
 50     update(val[u], d);
 51     for (int v: G[u]) {
 52         if (v != father && !centroid[v]) {
 53             dfs_up(v, u, d+1);
 54         }
 55     }
 56 }
 57 int res;
 58 void dfs_down(int u, int father, int d) {
 59     if (val[u] < val[father]) {
 60         return;
 61     }
 62     auto it = work.lower_bound(val[u]-D);
 63     if (it != work.end()) {
 64         res = max(res, it->second+1+d);
 65     }
 66     for (int v: G[u]) {
 67         if (!centroid[v] && v != father) {
 68             dfs_down(v, u, d+1);
 69         }
 70     }
 71 }
 72 
 73 void preSolve(int g, vector <int> &son) {
 74     work.clear();
 75     work[val[g]] = 0;
 76     for (int v: son) {
 77         if (val[v] >= val[g]) {
 78             dfs_down(v, g, 1);
 79         }
 80         if (val[v] <= val[g]) {
 81             dfs_up(v, g, 1);
 82         }
 83     }
 84 }
 85 void solve(int u) {
 86     dfs(u, 0);
 87     int g = FindCentroid(u, 0, siz[u]).second;
 88     vector <int> son;
 89     for (int v: G[g]) {
 90         if (!centroid[v]) {
 91             son.push_back(v);
 92         }
 93     }
 94     preSolve(g, son);
 95     reverse(son.begin(), son.end());
 96     preSolve(g, son);
 97     centroid[g] = true;
 98     for (int v: G[g]) {
 99         if (!centroid[v]) {
100             solve(v);
101         }
102     }
103 }
104 int main() {
105    // freopen("in.txt", "r", stdin);
106     int T, cas = 1;
107     scanf ("%d", &T);
108     while (T--) {
109         init();
110         scanf ("%d%d", &n, &D);
111         for (int i = 1; i <= n; i++) {
112             scanf ("%d", val+i);
113         }
114         for (int i = 1; i < n; i++) {
115             int u, v;
116             scanf ("%d%d", &u, &v);
117             G[u].push_back(v);
118             G[v].push_back(u);
119         }
120         res = 1;
121         solve(1);
122         printf("Case #%d: %d\n", cas++, res);
123     }
124     return 0;
125 }

 

转载于:https://www.cnblogs.com/oneshot/p/5001967.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园失物招领系统管理系统按照操作主体分为管理员和用户。管理员的功能包括字典管理、论坛管理、公告信息管理、失物招领管理、失物认领管理、寻物启示管理、寻物认领管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 校园失物招领系统管理系统可以提高校园失物招领系统信息管理问的解决效率,优化校园失物招领系统信息处理流程,保证校园失物招领系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 ,管理员权限操作的功能包括管理公告,管理校园失物招领系统信息,包括失物招领管理,培训管理,寻物启事管理,薪资管理等,可以管理公告。 失物招领管理界面,管理员在失物招领管理界面中可以对界面中显示,可以对失物招领信息的失物招领状态进行查看,可以添加新的失物招领信息等。寻物启事管理界面,管理员在寻物启事管理界面中查看寻物启事种类信息,寻物启事描述信息,新增寻物启事信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值