Magic Ball Game

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 2489    Accepted Submission(s): 759

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
  1. 1
  2. 3
  3. 2 3 1
  4. 1
  5. 1 2 3
  6. 3
  7. 3 2
  8. 1 1
  9. 3 4
 
Sample Output
  1. 0
  2. 0 0
  3. 1 3
  4.  
  5. 这道题目和HDU 5877 差不多。
  6. 两道题目都是在一棵树上进行操作,从树的根节点到某个节点的路径是唯一的,这个路径的所有节点形成的序列。
  7. 如果要在这个序列里进行各种操作,那么就要用树状数组或者线段树来解决。用树状数组要注意,在dfs回朔的时候
  8. 要删除点。如果用线段树来解决,那么可以有两种方式,一个是把线段树当做树状数组来用,毕竟树状数组能实现的东西
  9. 线段树都能实现。另外一种方式可以用可持续化线段树,就是在树的每一个点上面建立一个线段树,那么每个点上的线段树
  10. 就表示从根节点到这个节点的路径上所有点插到线段树里。
  11.  
  12. 可持续化线段树:
  13. #include <iostream>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <algorithm>
  17. #include <math.h>
  18. #include <stdio.h>
  19. #include <map>
  20. #include <vector>
  21. using namespace std;
  22. typedef long long int LL;
  23. const int maxn=1e5;
  24. vector<int> e[maxn+5];
  25. map<LL,int> mm;
  26. LL rt[maxn+5];
  27. LL ls[maxn*20+5];
  28. LL rs[maxn*20+5];;
  29. LL p2;
  30. LL p;
  31. int n,m,q;
  32. LL num[maxn*20+5][2];
  33. LL a[maxn+5];
  34. LL w[maxn+5];
  35. int Hash(LL x)
  36. {
  37.     return upper_bound(a+1,a+n+1,x)-a-1;
  38. }
  39. int newnode()
  40. {
  41.     ls[p]=rs[p]=num[p][0]=num[p][1]=0;
  42.     return p++;
  43. }
  44. void update(LL &node,int l,int r,LL tag,int flag)
  45. {
  46.     if(node==0)
  47.         node=newnode();
  48.     else
  49.     {
  50.         ls[p]=ls[node];
  51.         rs[p]=rs[node];
  52.         num[p][0]=num[node][0];
  53.         num[p][1]=num[node][1];
  54.         node=p++;
  55.     }
  56.     if(l==r)
  57.     {
  58.         num[node][flag]++;
  59.         return;
  60.     }
  61.     num[node][flag]++;
  62.     int mid=(l+r)>>1;
  63.     if(tag<=mid) update(ls[node],l,mid,tag,flag);
  64.     else update(rs[node],mid+1,r,tag,flag);
  65. }
  66. LL query(LL node,int l,int r,LL L,LL R,int flag)
  67. {
  68.     if(L>R) return 0;
  69.     if(!node) return 0;
  70.     if(L<=l&&r<=R)
  71.         return num[node][flag];
  72.     int mid=(l+r)>>1;
  73.     LL ret=0;
  74.     if(L<=mid)  ret+=query(ls[node],l,mid,L,R,flag);
  75.     if(R>mid)  ret+=query(rs[node],mid+1,r,L,R,flag);
  76.     return ret;
  77. }
  78. void dfs(int root)
  79. {
  80.     int len=e[root].size();
  81.     for(int i=0;i<len;i++)
  82.     {
  83.         int v=e[root][i];
  84.         update(rt[v]=rt[root],1,n,Hash(w[root]),i);
  85.         dfs(v);
  86.     }
  87. }
  88. int main()
  89. {
  90.     int t;
  91.     scanf("%d",&t);
  92.     LL x,y,z;
  93.     while(t--)
  94.     {
  95.         scanf("%d",&n);
  96.         for(int i=1;i<=n;i++)
  97.         {
  98.             e[i].clear();
  99.             scanf("%lld",&w[i]);
  100.             a[i]=w[i];
  101.         }
  102.         sort(a+1,a+n+1);
  103.         scanf("%d",&m);
  104.         for(int i=1;i<=m;i++)
  105.         {
  106.             scanf("%lld%lld%lld",&x,&y,&z);
  107.             e[x].push_back(y);
  108.             e[x].push_back(z);
  109.         }
  110.         memset(rt,0,sizeof(rt));
  111.         memset(num,0,sizeof(num));
  112.         p=1;
  113.         dfs(1);
  114.         scanf("%d",&q);
  115.         for(int i=1;i<=q;i++)
  116.         {
  117.             scanf("%lld%lld",&x,&y);
  118.             if(x==1) {printf("0 0\n");continue;}
  119.             int xx=Hash(y);
  120.             if(a[xx]==y)
  121.             {
  122.                 int num2=query(rt[x],1,n,xx,xx,0);
  123.                 int num5=query(rt[x],1,n,xx,xx,1);
  124.                 if(num2||num5)
  125.                 {
  126.                     printf("0\n");
  127.                     continue;
  128.                 }
  129.             }
  130.             LL num1=query(rt[x],1,n,1,xx,0);
  131.             LL num3=query(rt[x],1,n,xx+1,n,0);
  132.             LL num4=query(rt[x],1,n,1,xx,1);
  133.             LL num6=query(rt[x],1,n,xx+1,n,1);
  134.             LL ans1=3*(num1+num4)+num3+num6;
  135.             LL ans2=num4;
  136.             printf("%lld %lld\n",ans2,ans1);
  137.         }
  138.     }
  139.     return 0;
  140. }
  141. 树状数组:

  142. #include <iostream>
  143. #include <algorithm>
  144. #include <math.h>
  145. #include <stdlib.h>
  146. #include <stdio.h>
  147. #include <string.h>
  148. #include <vector>
  149. using namespace std;
  150. const int maxn=1e5;
  151. typedef long long int LL;
  152. int e[maxn+5][2];
  153. int c0[maxn+5];
  154. int c1[maxn+5];
  155. int n,m,q;
  156. int lowbit(int x) {return x&(-x);}
  157. int w[maxn+5];
  158. int vis[maxn+5];
  159. int a[maxn+5];
  160. vector<pair<int,int> > b[maxn+5];
  161. int ans1[maxn+5];
  162. int ans2[maxn+5];
  163. int Hash(int x)
  164. {
  165.     return upper_bound(a+1,a+n+1,x)-a-1;
  166. }
  167. void update0(int x,int tag)
  168. {
  169.     while(x<=n)
  170.     {
  171.         c0[x]+=tag;
  172.         x+=lowbit(x);
  173.     }
  174. }
  175. int sum0(int x)
  176. {
  177.     int num=0;
  178.     for(int i=x;i>=1;i-=lowbit(i))
  179.     {
  180.         num+=c0[i];
  181.     }
  182.     return num;
  183. }
  184. void update1(int x,int tag)
  185. {
  186.     while(x<=n)
  187.     {
  188.         c1[x]+=tag;
  189.         x+=lowbit(x);
  190.     }
  191. }
  192. int sum1(int x)
  193. {
  194.     int num=0;
  195.     for(int i=x;i>=1;i-=lowbit(i))
  196.     {
  197.         num+=c1[i];
  198.     }
  199.     return num;
  200. }
  201. void init()
  202. {
  203.     memset(c0,0,sizeof(c0));
  204.     memset(c1,0,sizeof(c1));
  205.     memset(vis,0,sizeof(vis));
  206.     memset(e,-1,sizeof(e));
  207.     memset(ans1,0,sizeof(ans1));
  208.     memset(ans2,0,sizeof(ans2));
  209.     for(int i=1;i<=n;i++)
  210.     {
  211.         b[i].clear();
  212.     }
  213. }
  214. void dfs(int root)
  215. {
  216.     for(int i=0;i<=1;i++)
  217.     {
  218.         if(e[root][i]==-1) continue;
  219.         int v=e[root][i];
  220.         if(!i) update0(Hash(w[root]),1);
  221.         else update1(Hash(w[root]),1);
  222.         if(vis[v])
  223.         {
  224.             int len=b[v].size();
  225.             for(int j=0;j<len;j++)
  226.             {
  227.                 int y=b[v][j].first;
  228.                 int x=b[v][j].second;
  229.                 int xx=Hash(y);
  230.                 if(a[xx]==y)
  231.                 {
  232.                     if((sum0(xx)-sum0(xx-1))!=0||(sum1(xx)-sum1(xx-1))!=0)
  233.                     {
  234.                         ans1[x]=-1;
  235.                         continue;
  236.                     }
  237.                 }
  238.                     int left_low=sum0(xx);
  239.                     int left_up=sum0(n)-sum0(xx);
  240.                     int right_low=sum1(xx);
  241.                     int right_up=sum1(n)-sum1(xx);
  242.                     ans1[x]=right_low;
  243.                     ans2[x]=3*(left_low+right_low)+left_up+right_up;
  244.             }
  245.         }
  246.         dfs(v);
  247.         if(!i) update0(Hash(w[root]),-1);
  248.         else update1(Hash(w[root]),-1);
  249.     }
  250. }
  251. int main()
  252. {
  253.     int t;
  254.     scanf("%d",&t);
  255.     while(t--)
  256.     {
  257.         int x,y,z;
  258.         scanf("%d",&n);
  259.         init();
  260.         for(int i=1;i<=n;i++)
  261.         {
  262.             scanf("%d",&w[i]);
  263.             a[i]=w[i];
  264.         }
  265.         sort(a+1,a+n+1);
  266.         scanf("%d",&m);
  267.         for(int i=1;i<=m;i++)
  268.         {
  269.             scanf("%d%d%d",&x,&y,&z);
  270.             e[x][0]=y;
  271.             e[x][1]=z;
  272.         }
  273.         scanf("%d",&q);
  274.         for(int i=1;i<=q;i++)
  275.         {
  276.             scanf("%d%d",&x,&y);
  277.             vis[x]=1;
  278.             b[x].push_back(make_pair(y,i));
  279.         }
  280.         dfs(1);
  281.         for(int i=1;i<=q;i++)
  282.         {
  283.             if(ans1[i]==-1) {printf("0\n");continue;}
  284.             else
  285.             {
  286.                 printf("%d %d\n",ans1[i],ans2[i]);
  287.             }
  288.         }
  289.     }
  290.     return 0;
  291. }

HDU 4605 Magic Ball Game(可持续化线段树,树状数组,离散化)的更多相关文章

  1. HDU 4605 Magic Ball Game (dfs+离线树状数组)

    题意:给你一颗有根树,它的孩子要么只有两个,要么没有,且每个点都有一个权值w. 接着给你一个权值为x的球,它从更节点开始向下掉,有三种情况 x=w[now]:停在此点 x<w[now]:当有孩子 ...

  2. hdu 4605 Magic Ball Game (在线主席树/离线树状数组)

    版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球 ...

  3. HDU 4605 Magic Ball Game 树状数组

    题目大意很简单. 有一颗树(10^5结点),所有结点要么没有子结点,要么有两个子结点.然后每个结点都有一个重量值,根结点是1 然后有一个球,从结点1开始往子孙结点走. 每碰到一个结点,有三种情况 如果 ...

  4. hdu 4605 Magic Ball Game

    http://acm.hdu.edu.cn/showproblem.php?pid=4605 可以离线求解 把所以可能出现的 magic ball  放在一个数组里(去重),从小到大排列 先不考虑特殊 ...

  5. HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意:给出一棵二叉树,每个结点孩子数目为0或者2. ...

  6. HDU 4605 Magic Ball Game 主席树

    题意: 给一棵\(n(1 \leq n \leq 10^5)\)个节点的二叉树,除叶子节点外,每个点都有左儿子和右儿子. 每个点上都有一个权值. 游戏规则是这样的:在根节点放一个权值为\(X\)的小球 ...

  7. HDU 4605 Magic Ball Game(离线算法)

    题目链接 思路就很难想+代码实现也很麻烦,知道算法后,已经写的很繁琐而且花了很长时间,200+,好久没写过这么长的代码了. #pragma comment(linker, "/STACK:1 ...

  8. hdu4605 树状数组+离散化+dfs

    Magic Ball Game Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. POJ 2299 【树状数组 离散化】

    题目链接:POJ 2299 Ultra-QuickSort Description In this problem, you have to analyze a particular sorting ...

随机推荐

  1. atitit.编程语言会形成进化树--哪些特性会繁荣??通才还是专才的选型 现代编程语言的特性总结

    atitit.编程语言会形成进化树--哪些特性会繁荣??通才还是专才的选型 现代编程语言的特性总结 1.  有一种观点,编程语言就像物种,会形成进化树,有的分支会死掉. 多年之后,你觉得语言会演化成什 ...

  2. codeblocks 配置OpenGL

    一.选择编译器环境 这里选择codeblocks,带MinGW的版本. 二.下载glut工具包 网址:http://pan.baidu.com/s/1eQriTQM 三.配置glut 解压缩下载的gl ...

  3. GPIO—位带操作

    GPIO—位带操作本章参考资料:< STM32F4xx 中文参考手册>存储器和总线构架章节. GPIO 章节,< Cortex®-M4 内核编程手册> 2.2.5 Bit-ba ...

  4. dp之01背包hdu3466(带限制的,当你所拥有的钱数大于某个限定值时才可以购买该物品)

    题意:买东西,每个东西有三个特征值,p代表价格,q代表你手中钱必须不低于q才能买这个物品,v代表得到的价值. mark:又是变种01背包,每做一个变种的,就是一种提高.. 按照q - p以由大到小的顺 ...

  5. jquery设置radio选中

    <script type="text/javascript"> $(document).ready(function(){ $("input[type=rad ...

  6. 嵌入式linux性能详解_转

    最近简单看了下<嵌入式Linux性能详解>一书,对系统内存分布测试.程序运行.动态库等都很很好的解析. 作者史子旺,loughsky@sina.com. 有时间希望仔细通读,并验证.

  7. asp.net 导出EXCEL超高兼容(不用装Excel)

    用网上的代码你会发现,下载下来后,会提示"你尝试打开的的文件的格式与文件扩展名指定的格式不一致 请验证文件没有损坏且来源可信的提示,研究了好久 后来发现可以使用人家做好的组件NOPI去实现, ...

  8. finals的使用

    //----------------------------------------Finals--------------------------- public class Finals { pu ...

  9. KMP + 求最小循环节 --- POJ 2406 Power Strings

    Power Strings Problem's Link: http://poj.org/problem?id=2406 Mean: 给你一个字符串,让你求这个字符串最多能够被表示成最小循环节重复多少 ...

  10. Thinkphp3.2 PHPMailer 发送 QQ邮箱 163邮箱

    在进入正题这前先看下网易(163)邮箱的服务器地址和端口号 类型 服务器名称 服务器地址 SSL协议端口号 非SSL协议端口号 收件服务器 POP pop.163.com 995 110 收件服务器 ...