HDU-4605-Magic Ball Game (离散化+树状数组+离线)

题目链接

题意:有一颗树,每个点有一个权值,从根节点放一个求往下落,球的值小于当前节点的值,往左右儿子落的概率各为1/2,相等则会停在这个节点,球的值大于当前节点的值往做儿子落的概率是1/8,往右儿子落的概率是7/8,q此询问,每个询问给一个点x和值w,问这个求落到x的概率。

思路:对于询问的每个点,只需要管跟节点到这个节点的这条链上的信息,用dfs可以很方便访问到每条链,把这条链分为向左和向右两部分,离散化所有权值后用树状数组维护每条链上的值的信息,对于每个节点的询问,只需要求出在这条链上值大于,等于,小于它的点各有多少个就好了,结果就很好算出来。

AC代码:

#include
using namespace std;
const int maxn=1e5+10;
vector vec,edge[maxn];
int val[maxn],vis[maxn],fa[maxn],n,root;
int getid(int x) { return lower_bound(vec.begin(),vec.end(),x)-vec.begin()+1; }
struct node
{
    int v,id;
    node(){};
    node(int vv,int iid){v=vv;id=iid;};
}ans[maxn];
vector Q[maxn];
int cnt[maxn],cnt2[maxn];
void add(int x,int val,int tp)
{
    if(tp==1){
        while(x<=n){
            cnt[x]+=val;
            x+=(x&-x);
        }
    }
    else{
        while(x<=n){
            cnt2[x]+=val;
            x+=(x&-x);
        }
    }
}
int sum(int x,int tp)
{
    int ans=0;
    if(tp==1){
        while(x>0){
            ans+=cnt[x];
            x-=(x&-x);
        }
    }
    else{
        while(x>0){
            ans+=cnt2[x];
            x-=(x&-x);
        }
    }
    return ans;
}
void dfs(int p)
{
    int num=Q[p].size();
    for(int i=0;i

 

你可能感兴趣的:(数据结构--树状数组)