UVALive 6584 Escape (Regionals 2013 >> Europe - Central)
2015-05-25 10:24
393 查看
题目
给出一棵树,每个节点有一个怪物或血药,遇到怪物必须打,打完后扣掉一定的血量。一开始英雄的血量为\(0\),当血量小于\(0\)时就挂了。
给出英雄的起点和终点,问能否成功到达终点。
算法
这题的方法真的是太美妙了!感觉ACM的题目比OI的好多了,因为它的程序不长,并且每题都不容易想啊。我们先来解决一个弱化版问题:把起点作为根,问英雄最多能加多少血。
我们可以想象每个点有一个礼包,这个礼包有两个属性,不妨用\((a,b)\)表示,表示当英雄的血量不少于\(a\)时可以加上\(b\)点血量(\(b\)是负数就减血量)。但是有些限制,如果要取某个礼包,那么它的所有祖先上的礼包都必须先取。
我们现在尝试对每棵子树维护一些礼包,首先要保证所有的礼包都是奖励的。我们不妨假设现在对于点\(v\),要根据它的所有儿子\(u_i\)的礼包合成点\(v\)子树的礼包。对于点\(v\),如果它有怪物,我们就要想办法通过提高\(a\)使得\(b\)变为非负数(提高\(a\)是为了取子树的礼包),如果不行,那么这棵子树是不可能走进去的(因为走进去就一定扣血啊)。
通过提高\(a\)的值,现在我们成功地在点\(v\)已经生成了一个礼包,如此下去,我们对于根就生成了一棵礼包树,每个点都是有奖励的!我们就贪心(先选\(a\)最小的)往下走就好了,这个贪心的话,可以用一个左偏树来维护礼包。每开启一个礼包,就把这个礼包的儿子也加进去。
解决了这个弱化版问题后,剩下的就简单了。
代码
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long i64; const int MAXN = (int) 2e5 + 3; int n, target; int A[MAXN]; struct Node{ Node* s[2]; int dis; i64 minus, plus; void init() { s[0] = s[1] = NULL; dis = 0; minus = plus = 0; } }; Node node[MAXN]; struct Edge { Edge* next; int to; }; Edge mem[MAXN * 2]; Edge* info[MAXN]; Edge* curMem; void insert(int a, int b) { curMem->to = b; curMem->next = info[a]; info[a] = curMem ++; } Node* merge(Node* x, Node* y) { if (! x) return y; if (! y) return x; if (x->minus > y->minus) swap(x, y); x->s[1] = merge(x->s[1], y); if (x->s[1] ? x->s[1]->dis : 0 > x->s[0] ? x->s[0]->dis : 0) swap(x->s[0], x->s[1]); x->dis = x->s[1] ? x->s[1]->dis + 1 : 1; return x; } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif scanf("%*d"); while (scanf("%d%d", &n, &target) == 2) { curMem = mem; memset(info, 0, sizeof info); for (int i = 1; i <= n; i ++) scanf("%d", A + i); for (int i = 1; i < n; i ++) { int v, u; scanf("%d%d", &v, &u); insert(v, u); insert(u, v); } static int que[MAXN]; static int fa[MAXN]; memset(fa, 0, sizeof fa); int low = 0, high = 0; que[high ++] = target; while (low < high) { int v = que[low ++]; for (Edge* pt = info[v]; pt; pt = pt->next) { int u = pt->to; if (u != fa[v]) { fa[u] = v; que[high ++] = u; } } } static bool path[MAXN]; memset(path, 0, sizeof path); for (int v = 1; v != 0; v = fa[v]) path[v] = true; for (int i = high - 1; i > 0; i --) { int v = que[i]; if (path[v]) continue; Node* son = NULL; for (Edge* pt = info[v]; pt; pt = pt->next) if (! path[pt->to] && pt->to != fa[v]) son = merge(son, &node[pt->to]); Node* cur = node + v; cur->init(); cur->minus = max(0, - A[v]); cur->plus = A[v]; while (son && (cur->plus < 0 || cur->minus > son->minus)) { if (cur->plus < 0) { cur->minus = max(cur->minus, son->minus - cur->plus); cur->plus += son->plus; } else { cur->plus += son->plus; } son = merge(son->s[0], son->s[1]); } cur = merge(cur, son); if (cur->plus < 0) cur = NULL; } i64 hp = 0; bool ok = true; Node* tree = NULL; for (int v = 1; v != 0; v = fa[v]) { hp += A[v]; if (hp < 0) { ok = false; break; } for (Edge* pt = info[v]; pt; pt = pt->next) { int u = pt->to; if (path[u]) continue; if (u == fa[v]) continue; tree = merge(tree, &node[u]); } while (tree && hp >= tree->minus) { hp += tree->plus; tree = merge(tree->s[0], tree->s[1]); } } if (ok) printf("escaped\n"); else printf("trapped\n"); } return 0; }
相关文章推荐
- UVALive 6931 Can't stop playing (Regionals 2014 >> Europe - Central)
- GREAT + SWERC = PORTO UVALive - 6884 Regionals 2014 >> Europe - Southwestern
- Regionals 2007 >> Europe - Southwestern Ladies' Choice 稳定婚姻问题 uva live 3989
- Regionals 2009 >> Asia - Hsinchu UVALIVE, 4528 Schedule Pairs of Jobs - 搜索回溯
- Regionals 2009 >> Asia - Hsinchu UVALIVE, 4529 A Constrained Queen Game - 搜索剪枝
- Regionals 2014 >> Europe - Central >> 6934 - Good morning!
- Regionals 2007 >> Asia - Nanjing - "Ray, Pass me the dishes!" 线段树 难 uva live 3938
- 2016 Europe - Northwestern I - Iron and Coal UVALive - 7767(最短路)
- UVALive Problem 7457 Discrete Logarithm Problem——Regionals 2015 :: Asia - Taipei
- 【UVALive】3029.City Game<C++>
- UVALive 6712(2013长春区域赛)
- UVAlive 3092 无根树->有根树 dfs
- Regionals 2009 :: Asia - Hsinchu UVALIVE, 4527 Vaccination Centers - 搜索剪枝
- UVALive 7147 World Cup(2014 Regionals 2014 :: Asia - ShangHai)
- ACM->uvalive->Sentry Robots(二分图匹配的最小点覆盖)
- UVa 306 / POJ 1026 / Central Europe 1995 Cipher (置换群)
- Regionals 2015 >> Europe - Northwestern >> 7429 - Guessing Camels【CDQ分治】
- Regionals 2015 >> Europe - Central >>7325 - Book Borders【模拟】
- UVALive Problem 7454 Parentheses——Regionals 2015 :: Asia - Taipei
- ACM-ICPC Live Archive Regionals 2014 >> 重拾2014上海区域赛