zoukankan      html  css  js  c++  java
  • 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
    ",ans[i][0],ans[i][1]);
    189             }
    190 
    191         }
    192 
    193     }
    194     return 0;
    195 }
    View Code

     

  • 相关阅读:
    POJ 2236 Wireless Network(并查集)
    POJ 2010 Moo University
    POJ 3614 Sunscreen(贪心,区间单点匹配)
    POJ 2184 Cow Exhibition(背包)
    POJ 1631 Bridging signals(LIS的等价表述)
    POJ 3181 Dollar Dayz(递推,两个long long)
    POJ 3046 Ant Counting(递推,和号优化)
    POJ 3280 Cheapest Palindrome(区间dp)
    POJ 3616 Milking Time(dp)
    POJ 2385 Apple Catching(01背包)
  • 原文地址:https://www.cnblogs.com/0803yijia/p/3224419.html
Copyright © 2011-2022 走看看