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 }
时间: 2024-10-24 01:12:52

UVALive 7148 LRIP 14年上海区域赛K题 树分治的相关文章

hdu5080:几何+polya计数(鞍山区域赛K题)

/* 鞍山区域赛的K题..当时比赛都没来得及看(反正看了也不会) 学了polya定理之后就赶紧跑来补这个题.. 由于几何比较烂写了又丑又长的代码,还debug了很久.. 比较感动的是竟然1Y了.. */ 题目大意: 给定一些点,某些点上有边,问用k种颜色染色的等价类有多少种 思路: 由于坐标是整数..只有可能旋转90,180,270才能得到置换 且图形必须为中心对称图形 先用几何方法找出对称中心 然后旋转,找是否出现置换... 由于点数只有50,几何预处理这一部分可以很暴力无脑的写..各种判断相

ACM 2015年上海区域赛A题 HDU 5572An Easy Physics Problem

题意: 光滑平面,一个刚性小球,一个固定的刚性圆柱体 ,给定圆柱体圆心坐标,半径 ,小球起点坐标,起始运动方向(向量) ,终点坐标 ,问能否到达终点,小球运动中如果碰到圆柱体会反射. 学到了向量模板,写法简洁. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define clc(a,b) sizeof(a,b,sizeof(a)) 6

2014上海区域赛 I题 Defeat the Enemy 离线读入 在线更新 线段树套优先队列

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5158 UVALive 7146 题意 自己有n个军队 敌方有m个军队 每个军队都有攻击力和防守力两种属性 当一方的攻击力>=对方的防御力时 可以把对方杀掉 在一次战斗中有可能出现双方都死了或者双方都没死的情况 另外要求己方不能有两只不同军队跟对方的同一只军队交

hdu 5137 去掉一个点 使得最短路最大(2014广州区域赛K题)

题意:从2~n-1这几个点中任意去掉一个点,使得从1到n的最短路径最大,如果任意去掉一个点1~n无通路输出Inf. Sample Input4 51 2 31 3 71 4 502 3 43 4 23 21 2 302 3 100 0 Sample Output50Inf 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 #

hdu 5122 (2014北京区域赛 K题)

把一个序列按从小到大排序 要执行多少次操作 只需要从右往左统计,并且不断更新最小值,若当前数为最小值,则将最小值更新为当前数,否则sum+1 Sample Input255 4 3 2 155 1 2 3 4 Sample OutputCase #1: 4Case #2: 1 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5

hdu 4463 有一条边必须加上 (2012杭州区域赛K题)

耐克店 和 苹果店必须相连 Sample Input42 30 01 00 -1 1 -10 Sample Output3.41 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # define LL long long 7 using namespace std ; 8

ACM学习历程——ZOJ 3829 Known Notation (2014牡丹江区域赛K题)(策略,栈)

Description Do you know reverse Polish notation (RPN)? It is a known notation in the area of mathematics and computer science. It is also known as postfix notation since every operator in an expression follows all of its operands. Bob is a student in

zoj 3829 Known Notation(2014年牡丹江区域赛k题)

Known Notation Time Limit: 2 Seconds      Memory Limit: 131072 KB Do you know reverse Polish notation (RPN)? It is a known notation in the area of mathematics and computer science. It is also known as postfix notation since every operator in an expre

Heshen&#39;s Account Book HihoCoder - 1871 2018北京区域赛B题(字符串处理)

Heshen was an official of the Qing dynasty. He made a fortune which could be comparable to a whole country's wealth by corruption. So he was known as the most corrupt official in Chinese history. But Emperor Qianlong liked, or even loved him so much