hdu 4605 Magic Ball Game(可持久化笛卡尔树)
2015-10-26 20:59
253 查看
题目链接:hdu 4605 Magic Ball Game
- X = W[u]时:小球停留在该节点
- X > W[u]时:小球有1/8的概率移动到左孩子,7/8的概率移动到右孩子
- X < W[u]时:小球有1/2的概率移动到左孩子,1/2的概率移动到右孩子
给定询问,x u,求小球会经过节点u的概率是多少。
这里用可持久化笛卡尔树做在线算法。对于每次询问,其实要求的即为节点u到根节点的路径上有多少个点的权值大于小球的质量,并且有多少个点是向右孩子移动的。
笛卡尔树中维护权值以及走向的个数。
以每个节点做一个版本的笛卡尔树,该版本的笛卡尔树维护的是节点u到根节点的情况。
题目大意
给定一棵二叉树,保证节点没有孩子节点或者有两个孩子节点,并且每个节点有一个权值W[i],1为根节点,树给定的方式m个关系u a b,表示u节点的左孩子为a,右孩子为b。现在从根节点放一个权值为X的小球:- X = W[u]时:小球停留在该节点
- X > W[u]时:小球有1/8的概率移动到左孩子,7/8的概率移动到右孩子
- X < W[u]时:小球有1/2的概率移动到左孩子,1/2的概率移动到右孩子
给定询问,x u,求小球会经过节点u的概率是多少。
解题思路
本题可以用两个树状数组做离线算法。这里用可持久化笛卡尔树做在线算法。对于每次询问,其实要求的即为节点u到根节点的路径上有多少个点的权值大于小球的质量,并且有多少个点是向右孩子移动的。
笛卡尔树中维护权值以及走向的个数。
以每个节点做一个版本的笛卡尔树,该版本的笛卡尔树维护的是节点u到根节点的情况。
代码
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int maxn = 1e5 + 5; /***********************************/ int P; struct Node { int key, val; int cnt, siz; int uri, sri, ch[2]; }nd[maxn * 20]; int newNode (int key, int rit) { P++; nd[P].key = key; nd[P].val = rand(); nd[P].cnt = nd[P].siz = 1; nd[P].uri = nd[P].sri = rit; nd[P].ch[0] = nd[P].ch[1] = 0; return P; } void maintain(int u) { int ls = nd[u].ch[0], rs = nd[u].ch[1]; nd[u].siz = nd[ls].siz + nd[rs].siz + nd[u].cnt; nd[u].sri = nd[ls].sri + nd[rs].sri + nd[u].uri; } void rotate(int& u, int d) { int k = nd[u].ch[d]; nd[u].ch[d] = nd[k].ch[d^1]; nd[k].ch[d^1] = u; maintain(u); maintain(k); u = k; } int insert(int v, int key, int rit) { if (v == 0) return newNode(key, rit); int u = ++P; nd[u] = nd[v]; if (nd[u].key == key) { nd[u].cnt++; if (rit) nd[u].uri++; } else { int d = nd[u].key < key; nd[u].ch[d] = insert(nd[u].ch[d], key, rit); if (nd[u].val < nd[nd[u].ch[d]].val) rotate(u, d); } maintain(u); return u; } bool query(int u, int key, int& x, int& y) { if (u == 0) return true; if (nd[u].key == key) return false; if (nd[u].key > key) return query(nd[u].ch[0], key, x, y); int ls = nd[u].ch[0]; x += nd[ls].sri + nd[u].uri; y += nd[ls].siz + nd[u].cnt; return query(nd[u].ch[1], key, x, y); } /***********************************/ int N, M, Q, F[maxn], W[maxn], L[maxn], R[maxn]; int T[maxn]; void dfs (int u, int rit) { if (u == 0) return; if (u != 1) T[u] = insert(T[F[u]], W[F[u]], rit); dfs(L[u], 0); dfs(R[u], 1); } void init () { scanf("%d", &N); for (int i = 1; i <= N; i++) scanf("%d", &W[i]); memset(L, 0, sizeof(L)); memset(R, 0, sizeof(R)); scanf("%d", &M); int u, a, b; while (M--) { scanf("%d%d%d", &u, &a, &b); F[a] = F[b] = u; L[u] = a; R[u] = b; } P = T[0] = 0; nd[P].cnt = nd[P].siz = 0; nd[P].uri = nd[P].sri = 0; nd[P].ch[0] = nd[P].ch[1] = 0; dfs(1, 0); } void solve (int u, int w) { int x = 0, y = 0; if (!query(T[u], w, x, y)) printf("0\n"); else printf("%d %d\n", x, y * 2 + nd[T[u]].siz); } int main () { int cas; scanf("%d", &cas); while (cas--) { init(); scanf("%d", &Q); int v, x; while (Q--) { scanf("%d%d", &v, &x); solve(v, x); } } return 0; }
相关文章推荐
- 关于iphone accessory的理解
- HDU-2159(FATE)
- 设计模式------工厂方法模式
- hibernate.hbm2ddl.auto配置详解
- 论架构师的自我修养
- 第一次驱动hello
- 机器学习中防止过拟合的处理方法
- Could not load file or assembly 'XXX' or one of its dependencies
- C++:多重继承
- oracle dba 使用mysql 时的痛点--待吐槽
- Android 理解生命周期最好例子—按home暂停音乐播放,跳转暂停
- 对称矩阵的压缩存储及基本运算(2)
- VS2013在文件中查找时无法显示查找结果
- 76 Minimum Window Substring
- 天声人語 20151026 「政治的」なものの忌避
- nginx之反向代理
- socket网络编程复习笔记(三):套接字描述符背后的秘密
- window 对象
- 使用正则表达式来验证日期格式是否为XX/XX/XXXX
- Android之自定义ViewPagerIndicator