hdu4605 Magic Ball Game(树状数组)

来源:互联网 发布:工控机软件开发 编辑:程序博客网 时间:2024/06/06 16:54

题目链接:点这里!!!!


题意:

给定一棵N(N<=1e5)节点的树,每个节点要么有两个儿子(左右两个儿子),要么没有儿子,每个节点有一个权值w[i]。

一个权值为X球从根节点开始下落,每落到一个节点的时候,

1.如果X=W[i],或者没有儿子节点了,球停止下落。

2.如果X<W[i],球各有1/2的概率落到左右儿子节点。

3.如果X>W[i],球有1/8的概率落到左儿子,有7/8的概率落到右儿子。

给你q(q<=1e5)个询问,询问中包含v,x。问你权值为x的球从根节点(根节点是1)落到v节点的概率是多少。(落不到输出0,否则概率用7^x/2^y表示,即输出x和y就可以。)


题解:

1、这道题我们可以对所有询问离线,相当于求当前节点到根节点的路径上有多少数大于它,有多少数小于它,有多少数等于它,我们可以直接用树状树状实现。


2、从根节点开始dfs,到达x节点时,取出其中的询问,树状数组里存的是根节点到father[x]中的权值,我可以快速求出其中大于、等于、小于它的数有多少。


3、这道题就OK了,具体看代码实现。


代码:

#include<cstdio>#include<cstring>#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<bitset>#include<set>#include<queue>#include<stack>#include<map>#include<cstdlib>#include<cmath>#define PI 2*asin(1.0)#define LL long long#define pb push_back#define pa pair<int,int>#define clr(a,b) memset(a,b,sizeof(a))#define lson lr<<1,l,mid#define rson lr<<1|1,mid+1,r#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)#define key_value ch[ch[root][1]][0]C:\Program Files\Git\binconst int  MOD = 1E9+7;const LL N = 2e5+15;const int maxn = 5e5+15;const int letter = 130;const int INF = 1e17;const double pi=acos(-1.0);const double eps=1e-10;using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int w[N],n,m,q,ps[N],cnt;int c[2][N],ans[N][2];vector<int>G[N];vector<pa>que[N];void init(){    cnt=0;    clr(c,0),clr(ans,0);    for(int i=0;i<N;i++) G[i].clear(),que[i].clear();}int lowbit(int x) {return x&(-x);}void update(int i,int val,int f){    for(int x=i;x<=cnt;x+=lowbit(x)) c[f][x]+=val;}int getsum(int i,int f){    int ans=0;    for(int x=i;x>0;x-=lowbit(x)) ans+=c[f][x];    return ans;}void dfs(int x){    for(int i=0;i<que[x].size();i++){        int id=que[x][i].first,pos=que[x][i].second;        pos=lower_bound(ps+1,ps+cnt+1,pos)-ps;        ///0 zuo   1you        int lqb=getsum(cnt,0);        int rqb=getsum(cnt,1);        int lx=getsum(pos-1,0);  ///xiaoyu        int rx=getsum(pos-1,1);        int ld=lqb-getsum(pos,0);        int rd=rqb-getsum(pos,1);        if(lx+ld+rx+rd!=lqb+rqb){            ans[id][0]=-1;            continue;        }        ans[id][0]=rx;        ans[id][1]=lx*3+rx*3+ld+rd;    }    for(int i=0;i<G[x].size();i++){        int vs=lower_bound(ps+1,ps+cnt+1,w[x])-ps;        update(vs,1,i);        dfs(G[x][i]);        update(vs,-1,i);    }}int main(){    int T;    scanf("%d",&T);    while(T--){        init();        scanf("%d",&n);        for(int i=1;i<=n;i++) scanf("%d",w+i),ps[++cnt]=w[i];        scanf("%d",&m);        for(int i=0;i<m;i++){            int u,a,b;            scanf("%d%d%d",&u,&a,&b);            G[u].pb(a),G[u].pb(b);        }        scanf("%d",&q);        for(int i=1;i<=q;i++){            int id,x;            scanf("%d%d",&id,&x);            que[id].pb(make_pair(i,x));            ps[++cnt]=x;        }        sort(ps+1,ps+cnt+1);        cnt=unique(ps+1,ps+cnt+1)-(ps+1);        dfs(1);        for(int i=1;i<=q;i++){            if(ans[i][0]==-1) puts("0");            else printf("%d %d\n",ans[i][0],ans[i][1]);        }    }    return 0;}/**/


0 0
原创粉丝点击