hdu4605 magic ball game 树状数组+离线处理

题意:给你一棵二叉树,每个节点有一个w值,现在有一颗小球,值为x,从根节点往下掉,如果w==x,那么它就会停止;如果w>x,那么它往左、右儿子的概率都是1、2;如果w<x,那么它往左儿子的概率是1/8,右儿子是7/8。现在给你q个询问,问你值为x的球道达节点u的概率为多少。

连接:http://acm.hdu.edu.cn/showproblem.php?pid=4605

思路:节点和询问比较多,可以储存询问集中处理。将所有的询问集中起来,与被询问的节点放在一起一起走,让所有节点的W值与被询问的W值都存起来排序,这样走过的节点设置为1没走过的为0这样就可以知道谁比他大谁比他小,另外设两个数组就可以知道是走了右边还是左边,这样线段树和树状数组都可以求解。

用宝哥的话说最后的答案就是:从一根节点u到一个点v存在的是唯一的一条确定的道路。我们只需要它在这条路上往左拐的情况中w的值(X可能大于该点的权值grtL,可能小于该点的权值lessL) 往右拐的情况中w的值(X可能大于该点的权值grtR,可能小于该点的权值lessR)  那么对于这个点的询问我们就可以知道:
x = grtR(只有它对7有贡献)  y = (lessL + lessR) + (grtL + grtR)*3; 

 

代码:(用g++ac,叫c++的话加上 #pragma comment(linker, "/STACK:1024000000,1024000000")

注意离散处理一下,让bsearch中不会出现相同的值,假设好多树节点的值相同,只需要+1即可。树状数组存的就是出现次数。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <stdlib.h>
  6 #include <queue>
  7 #include <vector>
  8 #define cl(a,b) memset(a,b,sizeof(a))
  9 #define loop(s,i,n) for(i = s;i < n;i++)
 10 
 11 const int maxn = 100005;
 12 using namespace std;
 13 struct ask
 14 {
 15     int num,turn;
 16 };
 17 struct node
 18 {
 19     int num,l,r;
 20 }g[maxn];
 21 int a[maxn*2];
 22 int b[maxn*2];
 23 int num[maxn*2];
 24 int suml[maxn*2];
 25 int sumr[maxn*2];
 26 vector<ask>q[maxn];
 27 int ans[maxn][2];
 28 int cnt;
 29 int lowbit(int x)
 30 {
 31     return  x&-x;
 32 }
 33 int sumleft(int x)
 34 {
 35     int ret;
 36     ret = 0;
 37     while(x > 0)
 38     {
 39         ret += suml[x];
 40         x-= lowbit(x);
 41     }
 42     return ret;
 43 }
 44 
 45 int sumright(int x)
 46 {
 47     int ret;
 48     ret = 0;
 49     while(x > 0)
 50     {
 51         ret += sumr[x];
 52         x-= lowbit(x);
 53     }
 54     return ret;
 55 }
 56 void addl(int x,int d)
 57 {
 58     while(x <= cnt)
 59     {
 60         suml[x] += d;
 61         x += lowbit(x);
 62     }
 63 }
 64 
 65 void addr(int x,int d)
 66 {
 67     while(x <= cnt)
 68     {
 69         sumr[x] += d;
 70         x += lowbit(x);
 71     }
 72 }
 73 int bsearch(int key)
 74 {
 75     int l,r,mid;
 76     l = 1;
 77     r = cnt;
 78     while(l <= r)
 79     {
 80         mid = (l+r)/2;
 81         if(b[mid] == key) return mid;
 82         if(key < b[mid]) r = mid-1;
 83         else l = mid+1;
 84     }
 85     return 0;
 86 }
 87 void dfs(int rt)
 88 {
 89     int i;
 90     int t,loc;
 91     for(i = 0;i < q[rt].size();i++)
 92     {
 93 
 94         t = q[rt][i].num;
 95         loc = bsearch(t);
 96         if(a[loc] > 0)
 97         {
 98             ans[q[rt][i].turn][0] = -1;
 99             ans[q[rt][i].turn][1] = -1;
100 
101           }
102         else{
103         ans[q[rt][i].turn][0] = sumright(loc);
104         ans[q[rt][i].turn][1] = 3*sumleft(loc)+sumleft(cnt)-sumleft(loc)+3*sumright(loc)+sumright(cnt)-sumright(loc);
105         }
106 
107     }
108     loc = bsearch(g[rt].num);
109     if(g[rt].l)
110     {
111         addl(loc,1);
112         a[loc]++;
113         dfs(g[rt].l);
114         addl(loc,-1);
115         a[loc]--;
116     }
117     if(g[rt].r){
118     addr(loc,1);
119     a[loc]++;
120     dfs(g[rt].r);
121     addr(loc,-1);
122     a[loc]--;
123     }
124     return ;
125 
126 }
127 int main()
128 {
129     int t;
130     cin>>t;
131     while(t--)
132     {
133         int m,n;
134         scanf("%d",&n);
135         cnt = 1;
136         int i;
137         memset(sumr,0,sizeof(sumr));
138         cl(suml,0);
139         cl(a,0);
140 
141 
142 
143         loop(1,i,n+1)
144             scanf("%d",&g[i].num),g[i].l = g[i].r = 0,num[cnt] = g[i].num,cnt++,q[i].clear();
145 
146         scanf("%d",&m);
147         while(m--)
148         {
149             int a,b,c;
150             scanf("%d %d %d",&a,&b,&c);
151             g[a].l = b;
152             g[a].r = c;
153         }
154         int k;
155         scanf("%d",&k);
156         loop(1,i,k+1)
157         {
158             int tmp,w;
159             scanf("%d %d",&tmp,&w);
160             struct ask temp;
161             temp.num = w;
162             temp.turn = i;
163             q[tmp].push_back(temp);
164             num[cnt++] = w;
165         }
166         cnt--;
167 
168         sort(num+1,num+cnt+1);
169         int zcnt;
170         zcnt = 0;
171         num[0] = 0;
172         for(i = 1;i <= cnt;i++)
173         {
174             if(num[i] != num[i-1])
175             b[++zcnt] = num[i];
176         }
177         cnt = zcnt;
178         dfs(1);
179         for(i = 1;i <= k;i++)
180         {
181             if(ans[i][0] == -1 || ans[i][1] == -1)
182             {
183                 puts("0");
184                 continue;
185             }
186             else
187             {
188                 printf("%d %d\n",ans[i][0],ans[i][1]);
189             }
190 
191         }
192 
193     }
194     return 0;
195 }
View Code

 

 

 

posted @ 2013-07-30 09:45  某某。  阅读(472)  评论(0编辑  收藏  举报