题意:一颗二叉树,任意节点要么有两个孩子要么没孩子。
然后有一个球,从结点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 }