HDU4605-Magic Ball Game

来源:互联网 发布:淘宝上的瘦身贴管用吗 编辑:程序博客网 时间:2024/05/17 17:42

Magic Ball Game

                                                                    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
                                                                                              Total Submission(s): 2598    Accepted Submission(s): 807


Problem Description
When the magic ball game turns up, Kimi immediately falls in it. The interesting game is made up of N balls, each with a weight of w[i]. These N balls form a rooted tree, with the 1st ball as the root. Any ball in the game has either 0 or 2 children ball. If a node has 2 children balls, we may define one as the left child and the other as the right child.
The rules are simple: when Kimi decides to drop a magic ball with a weight of X, the ball goes down through the tree from the root. When the magic ball arrives at a node in the tree, there's a possibility to be catched and stop rolling, or continue to roll down left or right. The game ends when the ball stops, and the final score of the game depends on the node at which it stops.
After a long-time playing, Kimi now find out the key of the game. When the magic ball arrives at node u weighting w[u], it follows the laws below:
1  If X=w[u] or node u has no children balls, the magic ball stops.
2  If X<w[u], there's a possibility of 1/2 for the magic ball to roll down either left or right.
3  If X>w[u], the magic ball will roll down to its left child in a possibility of 1/8, while the possibility of rolling down right is 7/8.
In order to choose the right magic ball and achieve the goal, Kimi wonders what's the possibility for a magic ball with a weight of X to go past node v. No matter how the magic ball rolls down, it counts if node v exists on the path that the magic ball goes along.
Manual calculating is fun, but programmers have their ways to reach the answer. Now given the tree in the game and all Kimi's queries, you're required to answer the possibility he wonders.
 

Input
The input contains several test cases. An integer T(T≤15) will exist in the first line of input, indicating the number of test cases.
Each test case begins with an integer N(1≤N≤105), indicating the number of nodes in the tree. The following line contains N integers w[i], indicating the weight of each node in the tree. (1 ≤ i ≤ N, 1 ≤ w[i] ≤ 109, N is odd)
The following line contains the number of relationships M. The next M lines, each with three integers u,a and b(1≤u,a,b≤N), denotes that node a and b are respectively the left child and right child of node u. You may assume the tree contains exactly N nodes and (N-1) edges.
The next line gives the number of queries Q(1≤Q≤105). The following Q lines, each with two integers v and X(1≤v≤N,1≤X≤109), describe all the queries.
 

Output
If the magic ball is impossible to arrive at node v, output a single 0. Otherwise, you may easily find that the answer will be in the format of 7x/2y . You're only required to output the x and y for each query, separated by a blank. Each answer should be put down in one line.
 

Sample Input
132 3 111 2 333 21 13 4
 

Sample Output
00 01 3
 

Source
2013 Multi-University Training Contest 1 
 

Recommend
liuyiding
 


题意:有一颗树有n个点,所有结点要么没有子结点,要么有两个子结点。然后每个结点都有一个重量值,根结点是1。有一个球,从根结点开始往子孙结点走。每碰到一个结点,有三种情况:

1.如果此球重量等于该结点重量,球就停下了

2.如果此球重量小于该结点重量,则分别往左右儿子走的可能都是1/2

3.如果此球重量大于该结点重量,则走向左儿子的概率是1/8,右儿子的概率是7/8

有q次询问,问一个重量为x的球经过结点v的概率

解题思路:一个球走到某个结点,路径已经是固定的了,可以发现路径可以分成两种,向左走的路径和向右走的路径,在向左走的路径中,设大于x的点权有a个,小于x的点权有b个,那么向左走的路径概率就是p1=(1/2)^a * (1/8) ^b, 同理向右的路径中概率p2 = (1/2)^c * (7/8) ^d,最后二者相乘即是答案。可以dfs整棵树,同时用两个树状数组分别维护向左走和向右走出现了哪些重量


#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <queue>#include <vector>#include <bitset>#include <functional>using namespace std;#define LL long longconst int INF = 0x3f3f3f3f;int n, m,q;int son[100005][2];int x[2][100005], ans[100005][2];int vis[100005], a[100005 << 1],w[100005];int s[100005], nt[100005 * 2], e[100005 * 2], id[100005 * 2];int lowbit(int k){return k&-k;}void add(int p, int k,int val){while (k <= m) x[p][k]+=val, k += lowbit(k);}int getsum(int p, int k){int sum = 0;while (k) sum += x[p][k], k -= lowbit(k);return sum;}void dfs(int k){for (int i = s[k]; ~i; i = nt[i]){int kk = lower_bound(a + 1, a + 1 + m, e[i]) - a;if (vis[kk]){ans[id[i]][0] = -1;continue;}int tmp1 = getsum(0, kk - 1), tmp2 = getsum(0, m) - tmp1;int tmp3 = getsum(1, kk - 1), tmp4 = getsum(1, m) - tmp3;ans[id[i]][0] = tmp3;ans[id[i]][1] = tmp1 * 3 + tmp2 + tmp3 * 3 + tmp4;}vis[w[k]] = 1;add(0, w[k],1);if (son[k][0]) dfs(son[k][0]);add(0, w[k], -1);add(1, w[k], 1);if (son[k][1]) dfs(son[k][1]);add(1, w[k], -1);vis[w[k]] = 0;}int main(){int t;scanf("%d", &t);while (t--){int cnt = 0;memset(son, 0, sizeof son);memset(s, -1, sizeof s);memset(vis, 0, sizeof vis);memset(x, 0, sizeof x);scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%d", &w[i]);a[i] = w[i];}scanf("%d", &m);for (int i = 1; i <= m; i++){int a, b, c;scanf("%d%d%d", &a, &b, &c);son[a][0] = b;son[a][1] = c;}scanf("%d", &q);for (int i = 1; i <= q; i++){int u, v;scanf("%d%d", &u, &v);a[i + n] = v;nt[cnt] = s[u], s[u] = cnt, e[cnt] = v, id[cnt++] = i;}sort(a + 1, a + n + q + 1);m = unique(a + 1, a + n + q + 1) - a - 1;for (int i = 1; i <= n; i++)w[i] = lower_bound(a + 1, a + 1 + m, w[i]) - a;dfs(1);for (int i = 1; i <= q; i++){if (ans[i][0] == -1) printf("0\n");else printf("%d %d\n", ans[i][0], ans[i][1]);}}return 0;}

原创粉丝点击