hdu 4605 树状数组 ****

题目大意很简单。

有一颗树(10^5结点),所有结点要么没有子结点,要么有两个子结点。然后每个结点都有一个重量值,根结点是1

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

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

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

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

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

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


仔细想一下,一个球走到某个结点,路径已经是固定的了,但是暴力肯定会超时,那么观察路径,可以发现路径可以分成两种,向左走的路径和向右走的路 径,分成这两种的原因也是因为各自的计算公式,在向左走的路径中,设大于x的点权有a个,小于x的点权有b个,那么向左走的路径概率就是p1= (1/2)^a * (1/8) ^b, 同理向右的路径中概率

p2 = (1/2)^c * (7/8) ^d,最后二者相乘即是答案。

p1*p2则分母的指数就是d,分子的指数即为d/(a+c+3*b+3*d)  

需要注意的是,如果从1到该点的路径中有一个点的重量等于x,那么这个点是永远被达不到的。

用树状数组维护指数即可


  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <map>
  7 #include <vector>
  8 using namespace std;
  9 const int MAXN=400010;
 10 int next[MAXN][2];
 11 int n;
 12 int root;
 13 int w[MAXN];
 14 struct QQ
 15 {
 16     int v;
 17     int X;
 18     int ans1,ans2;
 19 }Query[MAXN];
 20 vector<int>vec[MAXN];
 21 bool used[MAXN];
 22 int a[MAXN];
 23 map<int,int>mp;
 24 
 25 int c1[MAXN];
 26 int c2[MAXN];
 27 int t;
 28 int lowbit(int x)
 29 {
 30     return x&(-x);
 31 }
 32 void add1(int i,int val)
 33 {
 34     while(i <= t)
 35     {
 36         c1[i] += val;
 37         i += lowbit(i);
 38     }
 39 }
 40 int sum1(int i)
 41 {
 42     int s = 0;
 43     while(i > 0)
 44     {
 45         s += c1[i];
 46         i -= lowbit(i);
 47     }
 48     return s;
 49 }
 50 void add2(int i,int val)
 51 {
 52     while(i <= t)
 53     {
 54         c2[i] += val;
 55         i += lowbit(i);
 56     }
 57 }
 58 int sum2(int i)
 59 {
 60     int s = 0;
 61     while(i > 0)
 62     {
 63         s += c2[i];
 64         i -= lowbit(i);
 65     }
 66     return s;
 67 }
 68 
 69 void dfs(int u)
 70 {
 71     int sz = vec[u].size();
 72     for(int i = 0;i < sz;i++)   //对于每个点上的询问
 73     {
 74         int id = vec[u][i];
 75         int X = mp[Query[id].X];
 76         if(sum1(X)-sum1(X-1)!=0 || sum2(X)-sum2(X-1)!=0)
 77         {
 78             Query[id].ans1 = Query[id].ans2 = -1;
 79         }
 80         else
 81         {
 82             Query[id].ans1 = Query[id].ans2 = 0;
 83             Query[id].ans2 += 3*sum1(X-1)+sum1(t)-sum1(X);
 84             Query[id].ans1 += sum2(X-1);
 85             Query[id].ans2 += 3*sum2(X-1)+sum2(t)-sum2(X);
 86         }
 87     }
 88     if(next[u][0]==0 && next[u][1]==0)return;
 89     add1(mp[w[u]],1);       //保证是有序的
 90     dfs(next[u][0]);    //左走
 91     add1(mp[w[u]],-1);  //恢复
 92     add2(mp[w[u]],1);   //右走
 93     dfs(next[u][1]);
 94     add2(mp[w[u]],-1);  //回溯法
 95 }
 96 
 97 int main()
 98 {
 99     //freopen("in.txt","r",stdin);
100     //freopen("out.txt","w",stdout);
101     int T;
102     int m;
103     int u,x,y;
104     scanf("%d",&T);
105     while(T--)
106     {
107         scanf("%d",&n);
108         for(int i = 1;i <= n;i++)
109         {
110             used[i] = false;
111             next[i][0] = next[i][1] = 0;
112             vec[i].clear();
113         }
114         t = 0;
115         for(int i = 1;i <= n;i++)
116         {
117             scanf("%d",&w[i]);
118             a[t++] = w[i];
119         }
120         scanf("%d",&m);
121         while(m--)
122         {
123             scanf("%d%d%d",&u,&x,&y);
124             used[x] = true;
125             used[y] = true;
126             next[u][0] = x;
127             next[u][1] = y;
128         }
129         scanf("%d",&m);
130         for(int i = 0;i < m;i++)
131         {
132             scanf("%d%d",&u,&x);
133             Query[i].v = u;
134             Query[i].X = x;
135             a[t++] = x;
136             vec[u].push_back(i);
137         }
138         for(int i = 1;i <= n;i++)
139             if(!used[i])
140             {
141                 root = i;
142                 break;
143             }
144         sort(a,a+t);
145         t = unique(a,a+t)-a;
146         mp.clear();
147         for(int i = 0;i < t;i++)
148             mp[a[i]]=i+1;
149         memset(c1,0,sizeof(c1));
150         memset(c2,0,sizeof(c2));
151         dfs(root);
152         for(int i = 0;i < m;i++)
153         {
154             if(Query[i].ans1 == -1)
155                 printf("0
");
156             else printf("%d %d
",Query[i].ans1,Query[i].ans2);
157         }
158     }
159     return 0;
160 }
原文地址:https://www.cnblogs.com/cnblogs321114287/p/4596867.html