zoukankan      html  css  js  c++  java
  • HDU4605 Magic Ball Game

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


    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
    3
    2 3 1
    1
    1 2 3
    3
    3 2
    1 1
    3 4
     
    Sample Output
    0
    0 0
    1 3
     
    Source

     主席树。中序遍历,按顺序将节点建树。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstdlib> 
      4 #include <cstring>
      5 #include <cstdio>
      6 const int N = 100000 + 3 ;
      7 using namespace std;
      8 int t,n,m,q,w[N],li[N],tot,root[N],roots,cnt;
      9 bool ru[N];
     10 struct id
     11 {
     12     int lson,rson;
     13 } id_tree[N];
     14 struct seg
     15 {
     16     int l,r,sum[2];//0 -> left_sum ; 1 -> right_sum  
     17 }tree[N*30];
     18 
     19 void Init( )
     20 {
     21     scanf("%d",&n);
     22     for(int i = 1;i <= n; ++i)
     23     {
     24         scanf("%d",w+i); 
     25         li[i] = w[i];
     26     }
     27     sort(li+1,li+1+n); tot = 1;
     28     for(int i = 2; i <= n; ++i) if(li[i] != li[tot]) li[++tot] = li[i];    
     29     scanf("%d",&m); int a,u,v;
     30     memset(id_tree,0,sizeof(id_tree));
     31     memset(ru,0,sizeof(ru));
     32     for(int i = 1; i <= m; ++i)
     33     {
     34         scanf("%d%d%d",&a,&u,&v);
     35         id_tree[a].lson = u , id_tree[a].rson = v;
     36         ru[u] = true , ru[v] = true;
     37     }    
     38     for( int i = 1; i <= n; ++i )
     39     {
     40         if(ru[i] == false)
     41         { 
     42             roots = i;
     43             break;
     44         }
     45     }
     46 }
     47 
     48 int binary_search( int num )
     49 {
     50     int l = 1 , r = tot,ret = tot+1;
     51     while( l <= r )
     52     {
     53         int mid = l + ((r-l)>>1);
     54         if( li[mid] == num ) return mid;
     55         if( li[mid] < num ) l = mid + 1 ;
     56         else r = mid - 1 , ret = min(tot,mid);
     57     }
     58     return ret;
     59 }
     60 
     61 
     62 void updata(int l,int r,int &x,int y,int pos,int id)
     63 {
     64     tree[++cnt] = tree[y] ; x = cnt; ++tree[cnt].sum[id];
     65     if( l == r ) return;
     66     int mid = l + ((r-l)>>1) ;
     67     if( pos <= mid ) updata(l,mid,tree[x].l,tree[y].l,pos,id);
     68     else updata(mid+1,r,tree[x].r,tree[y].r,pos,id);
     69 }
     70 
     71 void dfs(int u)
     72 {
     73     int l = id_tree[u].lson , r = id_tree[u].rson;
     74     if(l == r && r == 0) return;
     75     int add = binary_search( w[u] );
     76     updata(1,tot,root[l],root[u],add,0);
     77     dfs( l );
     78     updata(1,tot,root[r],root[u],add,1);
     79     dfs( r );
     80 }
     81 
     82 
     83 int query(int l,int r,int num,int L,int R,int id)
     84 {
     85     if( L > R ) return 0;
     86     if( l == L && r == R ) return tree[num].sum[id];
     87     int mid =l + ((r-l)>>1);
     88     if( R <= mid ) return query(l,mid,tree[num].l,L,R,id);
     89     else if( L > mid ) return query(mid+1,r,tree[num].r,L,R,id);
     90     return query(l,mid,tree[num].l,L,mid,id) + query(mid+1,r,tree[num].r,mid+1,R,id);
     91 }
     92 
     93 
     94 void Solve( )
     95 {
     96     memset(tree,0,sizeof(tree)); cnt = 0;
     97     dfs( roots ) ;
     98     scanf("%d",&q);
     99     int v,X;
    100     while(q--)
    101     {
    102         scanf("%d%d",&v,&X);
    103         if( v == 1 )
    104         {
    105             printf("0 0
    ");
    106             continue;
    107         }
    108         int r = binary_search( X ) ; int l = r - 1;
    109         if( li[r] == X )
    110         {
    111             if(query(1,tot,root[v],r,r,0) + query(1,tot,root[v],r,r,1) > 0)
    112             {    
    113                 puts("0") ;
    114                 continue ;
    115             }
    116         }
    117         int r_less = query(1,tot,root[v],1,l,1), r_more = query(1,tot,root[v],r,tot,1);
    118         int l_less = query(1,tot,root[v],1,l,0), l_more = query(1,tot,root[v],r,tot,0);
    119         int x = r_less, y = 3*(r_less + l_less) + r_more + l_more;
    120 
    121         printf("%d %d
    ",x,y);
    122     }
    123 }
    124 
    125 int main()
    126 {
    127     scanf("%d",&t);
    128     while(t--)
    129     {
    130         Init();    
    131         Solve();
    132     }
    133     fclose(stdin);
    134     fclose(stdout);
    135     return 0;
    136 }
  • 相关阅读:
    winform 监视DataGridView的滚动条,加载数据
    SQL 自动生成行号
    SQL 删除重复的数据(多个字段判断),只保留一条数据
    C# 一个简单的 工厂模式 例子
    winform 重写TextBox的OnTextChanged方法(事件)
    winform 给文本框加载内容的时候 始终让文本框的滚动条到底(允许显示多行Multiline=True)
    winform 制定DataGridViewTextColumn列(更改DataGridView的Cell的状态很有用)
    winform 使用委托 实现多线程访问控件
    C# 一个简单的递归函数和 两个List<T> 合并
    ADO.NET  把数据库A的某表的数据内容复制到数据库B的某表内
  • 原文地址:https://www.cnblogs.com/Ateisti/p/6367703.html
Copyright © 2011-2022 走看看