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\n");
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\n");
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\n",ans1,ans2);
176         }
177     }
178     return 0;
179 }

 

posted @ 2014-12-03 22:01  PlasticSpirit  阅读(418)  评论(0编辑  收藏  举报