题意:给你一棵二叉树,每个节点有一个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即可。树状数组存的就是出现次数。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }