• 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 }
  • 相关阅读:
    VLC 播放完毕后自动退出的问题
    配置Linux文件句柄数
    java获取某一天的邮件
    oracle wm_concat函数将多行转字段函数
    Vue学习(二十五)TS支持
    Vue学习(二十四)render函数
    Vue学习(二十三)路由全攻略
    git commit规范&工具安装使用
    Vue学习(二十二)自定义指令全攻略
    Vue学习(二十一)$emit全攻略
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4596867.html
Copyright © 2020-2023  润新知