hdu 4605 Magic Ball Game

题意:有T组测试数据,N表示这棵树有N个点,下一行的N个数,表示每个点的权值W,M表示边的关系,接下来的M行,每行有三个数字,u,b,b,表示点a和点b分别是点u的左儿子和右儿子。Q表示查询数,接下来的Q行,每行两个数字,v和X。

        一个权值为X球从根节点开始下落,每落到一个节点的时候,1.如果X=W[i],或者没有儿子节点了,球停止下落。2.如果X<W[i],球各有1/2的概率落到左右儿子节点。3.如果X>W[i],球有1/8的概率落到左儿子,有7/8的概率落到右儿子。问球落到点v的概率是多少(概率用7^x/2^y表示,即输出x和y就可以)?

        当知道点v的时候,我们要统计的是,从根节点到点v上有多少个节点权值是大于X的,有多少个节点权值是小于X的(并且分别是在左儿子还是右儿子),是否有节点的权值与X相等。用两棵树状数组维护(代表是在左儿子还是在右儿子),直接DFS一次,将DFS路径上的权值加入对应线状数组里,然后统计就可以了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

const int N=1e5+5;

#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))

struct OP
{
    int w,idx;
    OP(){}
    OP(int w,int idx) : w(w),idx(idx) {}
};
struct BIT
{
    int T[N*2],LIM;
    void init(int n)
    {
        LIM=n;
        memset(T,0,sizeof(T));
    }

    int lowbit(int x){return x&(-x);}
    void updata(int pos,int valu)
    {
        for(int i=pos;i<=LIM;i+=lowbit(i)) T[i]+=valu;
    }
    int query(int st,int ed)
    {
        int sum=0;
        for(int i=ed;i>0;i-=lowbit(i)) sum+=T[i];
        for(int i=st-1;i>0;i-=lowbit(i)) sum-=T[i];
        return sum;
    }
}seg[2];

int n,m,K;
int W[N],len,adj[N][2];
int ans1[N],ans2[N];

map<int,int> H;
vector<int> Y;
vector<OP> op[N];

void fun(int u)
{
    for(int i=0;i<(int)op[u].size();i++)
    {
        int id=H[ op[u][i].w ],idx=op[u][i].idx;
        ans1[idx]=ans2[idx]=0;

        if(seg[0].query(id,id)||seg[1].query(id,id)) ans1[idx]=-1;
        else
        {
            ans2[idx]+=seg[0].query(1,id)*3;
            ans2[idx]+=seg[0].query(id,len);

            int tmp=seg[1].query(1,id);
            ans1[idx]+=tmp;
            ans2[idx]+=tmp*3;
            ans2[idx]+=seg[1].query(id,len);
        }
    }
}
void dfs(int u)
{
    int id=H[W[u]];
    for(int i=0;i<2;i++)
    {
        int v=adj[u][i];
        if(v==-1) break;

        seg[i].updata(id,1);

        fun(v);
        dfs(v);

        seg[i].updata(id,-1);
    }
}
int main()
{
    //freopen("06.in","r",stdin);

    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);

        Y.clear(); H.clear();

        for(int i=1;i<=n;i++)
        {
            op[i].clear();        adj[i][0]=adj[i][1]=-1;

            scanf("%d",&W[i]);
            Y.push_back(W[i]);
        }

        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int u,a,b; scanf("%d%d%d",&u,&a,&b);
            adj[u][0]=a; adj[u][1]=b;
        }

        scanf("%d",&K);
        for(int i=0;i<K;i++)
        {
            int v,w; scanf("%d%d",&v,&w);
            Y.push_back(w);
            op[v].push_back(OP(w,i));
        }

        sort(Y.begin(),Y.end());
        Y.erase( unique(Y.begin(),Y.end()),Y.end());
        for(int i=0;i<(int)Y.size();i++) H[Y[i]]=i+1;

        len=(int)Y.size();

        seg[0].init(len+5); seg[1].init(len+5);

        fun(1);        dfs(1);

        for(int i=0;i<K;i++)
        {
            if(ans1[i]==-1) puts("0");
            else printf("%d %d\n",ans1[i],ans2[i]);
        }
    }
    return 0;
}


你可能感兴趣的:(hdu 4605 Magic Ball Game)