zoukankan      html  css  js  c++  java
  • HDU4605---Magic Ball Game(主席树 好题)

    题意:一颗二叉树,任意节点要么有两个孩子要么没孩子。

    然后有一个球,从结点1开始往子孙结点走。

    每碰到一个结点,有三种情况

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

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

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

    然后若干个询问(10^5次),问一个重量为x的球经过结点v的概率

    观察路径,可以发现路径可以分成两种,向左走的路径和向右走的路径,分成这两种是因为各自的计算公式,在向左走的路径中,设大于x的点权有a个,小于x的点权有b个,同理定义c d,我们只需要求出a b c d 就可以了。

    做法:

    貌似很多做法,,我是用主席树多的,对于节点V,建立根节点1到V的前缀线段树,(此过程bfs实现)利用主席树的性质。

    然后主席树里面存两个信息,一个是向左走的一个是向右走的。(此题一些细节,二分的时候不注意的话就会一直wa)

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <algorithm>
      4 #include <queue>
      5 #include <cstring>
      6 using namespace std;
      7 
      8 const int maxn = 1e5+10;
      9 struct Edge
     10 {
     11     int to,next,kind;
     12 } e[maxn<<1];
     13 int head[maxn],edge_idx;
     14 void add_edge(int x,int y,int kind)
     15 {
     16     e[edge_idx].to = y;
     17     e[edge_idx].next = head[x];
     18     e[edge_idx].kind = kind;
     19     head[x] = edge_idx++;
     20 }
     21 //----------------------------------
     22 int lcnt[maxn*30],rcnt[maxn*30],lson[maxn*30],rson[maxn*30];
     23 int tree[maxn<<1],tot,tree_max;
     24 int build (int l,int r)
     25 {
     26     int root = tot++;
     27     lcnt[root] = rcnt[root] = 0;
     28     if (l != r)
     29     {
     30         int mid = (l + r) >> 1;
     31         lson[root] = build(l,mid);
     32         rson[root] = build(mid+1,r);
     33     }
     34     return root;
     35 }
     36 int update (int root,int pos,int lval,int rval)
     37 {
     38     int newroot = tot++;
     39     int tmp = newroot;
     40     int l = 1,r = tree_max;
     41     lcnt[newroot] = lcnt[root] + lval;
     42     rcnt[newroot] = rcnt[root] + rval;
     43     while (l < r)
     44     {
     45         int mid = (l + r) >> 1;
     46         if (pos <= mid)
     47         {
     48             r = mid;
     49             rson[newroot] = rson[root];
     50             root = lson[root];
     51             lson[newroot] = tot++;
     52             newroot = lson[newroot];
     53         }
     54         else
     55         {
     56             l = mid + 1;
     57             lson[newroot] =lson[root];
     58             root = rson[root];
     59             rson[newroot] = tot++;
     60             newroot = rson[newroot];
     61         }
     62         lcnt[newroot] = lcnt[root] + lval;
     63         rcnt[newroot] = rcnt[root] + rval;
     64     }
     65     return tmp;
     66 }
     67 int query(int root,int l,int r,int ua,int ub,int kind)
     68 {
     69     if (ub < ua)
     70         return 0;
     71     if (ua <= l && ub >= r)
     72     {
     73         if (kind)
     74             return rcnt[root];
     75         else
     76             return lcnt[root];
     77     }
     78     int mid = (l + r) >> 1;
     79     int t1 = 0, t2 = 0;
     80     if (ua <= mid)
     81         t1 = query(lson[root],l,mid,ua,ub,kind);
     82     if (ub > mid)
     83         t2 = query(rson[root],mid+1,r,ua,ub,kind);
     84     return t1 + t2;
     85 }
     86 
     87 int W[maxn],vec[maxn],idx;
     88 int hash_(int x)
     89 {
     90     return lower_bound(vec,vec+idx,x) - vec + 1;
     91 }
     92 void init()
     93 {
     94     memset(head,-1,sizeof(head));
     95     idx = tot = 0;
     96     edge_idx = 0;
     97 }
     98 int main(void)
     99 {
    100 #ifndef ONLINE_JUDGE
    101     freopen("in.txt","r",stdin);
    102 #endif
    103     int T;
    104     scanf ("%d",&T);
    105     while (T--)
    106     {
    107         init();
    108         int n,q,m;
    109         scanf ("%d",&n);
    110         for (int i = 0; i < n ; i++)
    111         {
    112             scanf ("%d",W+i+1);
    113             vec[idx++] = W[i+1];
    114         }
    115         sort(vec,vec+idx);
    116         idx = unique(vec,vec+idx) - vec;
    117         scanf ("%d",&m);
    118         for (int i = 0; i < m; i++)
    119         {
    120             int x,lf,rg;
    121             scanf ("%d%d%d",&x,&lf,&rg);
    122             add_edge(x,lf,0);
    123             add_edge(x,rg,1);
    124         }
    125         tree_max = n;
    126         tree[1] = build(1,n);
    127 
    128         queue<int>Q;
    129         while (!Q.empty())
    130             Q.pop();
    131         Q.push(1);
    132         while (!Q.empty())
    133         {
    134             int x = Q.front();
    135             Q.pop();
    136             for (int i = head[x]; ~i; i = e[i].next)
    137             {
    138                 int v,k;
    139                 v = e[i].to, k = e[i].kind;
    140                 tree[v] = update(tree[x],hash_(W[x]),k == 0, k == 1);
    141                 Q.push(v);
    142             }
    143         }
    144         scanf ("%d",&q);
    145         for (int i = 0; i < q; i++)
    146         {
    147             int x,v;
    148             scanf ("%d%d",&v,&x);
    149             if (v == 1)
    150             {
    151                 printf("0 0
    ");
    152                 continue;
    153             }
    154             int tmp = x;             //
    155             x = hash_(x);            // 二分得到的值可能原数组并不存在
    156             int ua = x-1, ub = x;   //理论上要查询x+1,但是如果tmp在原数组中不存在,那么就不用+1了
    157             int flag = 0;
    158             flag = query(tree[v],1,n,x,x,0) + query(tree[v],1,n,x,x,1);
    159             if (vec[x-1] == tmp)
    160             {
    161                 if (flag)
    162                 {
    163                     printf("0
    ");
    164                     continue;
    165                 }
    166                 ub++;
    167             }
    168             int lf_small = query(tree[v], 1, n, 1,   ua, 0);
    169             int lf_big   = query(tree[v], 1, n, ub, n,   0);
    170             int rg_small = query(tree[v], 1, n, 1,   ua, 1);
    171             int rg_big   = query(tree[v], 1, n, ub, n,   1);
    172             int ans1 = 0, ans2 = 0;
    173             ans1 += rg_small;
    174             ans2 += 3*(rg_small+lf_small) + rg_big + lf_big;
    175             printf("%d %d
    ",ans1,ans2);
    176         }
    177     }
    178     return 0;
    179 }
  • 相关阅读:
    权值线段树模版
    P2679 [NOIP2015 提高组] 子串
    P3747 [六省联考 2017] 相逢是问候
    P2822 [NOIP2016 提高组] 组合数问题
    P2331 [SCOI2005]最大子矩阵
    P1854 花店橱窗布置
    P5888 传球游戏
    Hard | LeetCode 42. 接雨水 | 单调栈 | 双指针
    Medium | LeetCode 621. 任务调度器 | 设计
    Medium | LeetCode 166. 分数到小数 | 数学
  • 原文地址:https://www.cnblogs.com/oneshot/p/4141432.html
Copyright © 2011-2022 走看看