hdu 4605 Magic Ball Game

来源:互联网 发布:淘宝兼职客服一般多少 编辑:程序博客网 时间:2024/05/20 16:36

题意:给出一棵二叉树,树上每个节点都有一个权值w[i],从根节点向下扔一个权值为x的小球,小球到达每个节点有三种情况:①x==w[u],小球停止运动 ②x<w[u],小球有相同的概率向左或向右走 ③x>w[u],小球有1/8的概率向左走,有7/8的概率向右走。有q个询问,每个询问有两个值v、x,回答从根节点扔小球,小球停在v或经过v的概率。

思路:由于一棵树从根节点到任意一个节点的路径是唯一的,那么我们只要将询问离散化,然后用一个数据结构去维护走过的路径上的权值就行了,没走到一个结点,就回答和这个节点有关的询问。我用的线段树维护,因为小球向左向右走的概率跟该节点的权值和小球的权值有关,那么我们可以维护两颗线段树,一棵是从根节点到v的路径中向左走的节点的权值,一棵是从根节点到v的路径中向右走的节点的权值,然后就可以很简单的查到比小球权值大(小)的节点的个数,答案算起来也不难。走过某一节点后,就把这个节点从所选的数据结构中删掉就行了。当时多校做完以后看了题解没看懂Orz,今天也研究了好半天……但这题果断很好啊

 

代码:

 

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;typedef long long ll;const int maxn=100000+10;int lson[maxn],rson[maxn],rnk[maxn];int ans1[maxn],ans2[maxn],ww[maxn];bool flag[maxn];int n,m,q,cnt,lf,rn;struct Node{    int u,w;    bool operator < (const Node &a) const    {        return w<a.w;    }};Node node[maxn];vector<Node>querys[maxn];int maxv[maxn<<1][2],minv[maxn<<1][2],sum[maxn<<1][2];void Init(){    memset(lson,0xff,sizeof(lson));    memset(rson,0xff,sizeof(rson));    memset(flag,0,sizeof(flag));    for(int i=1;i<=n;++i) querys[i].clear();}void PushUp(int rt,int h){    sum[rt][h]=sum[rt<<1][h]+sum[rt<<1|1][h];    maxv[rt][h]=max(maxv[rt<<1][h],maxv[rt<<1|1][h]);    minv[rt][h]=min(minv[rt<<1][h],minv[rt<<1|1][h]);}void build(int l,int r,int rt){    sum[rt][0]=sum[rt][1]=0;    maxv[rt][0]=maxv[rt][1]=-1;    minv[rt][0]=minv[rt][1]=inf;    if(l==r) return ;    int m=(l+r)>>1;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);}int Query1(int l,int r,int rt,int v,int h){    if(maxv[rt][h]<v) return sum[rt][h];    if(minv[rt][h]>=v||l==r) return 0;    int m=(l+r)>>1;    int ls=rt<<1,rs=rt<<1|1;    if(maxv[ls][h]<v)      return sum[ls][h]+Query1(m+1,r,rs,v,h);    else return Query1(l,m,ls,v,h);}int Query2(int l,int r,int rt,int v,int h){    if(minv[rt][h]>v) return sum[rt][h];    if(maxv[rt][h]<=v||l==r) return 0;    int m=(l+r)>>1;    int ls=rt<<1,rs=rt<<1|1;    if(minv[rs][h]>v)      return sum[rs][h]+Query2(l,m,ls,v,h);    else return Query2(m+1,r,rs,v,h);}void Update(int p,int l,int r,int rt,int v,int h){    if(l==r)    {        if(v<0)        {            maxv[rt][h]=-1;minv[rt][h]=inf;            sum[rt][h]=0;        }        else        {            maxv[rt][h]=minv[rt][h]=v;            sum[rt][h]=1;        }        return;    }    int m=(l+r)>>1;    if(p<=m)      Update(p,l,m,rt<<1,v,h);    else Update(p,m+1,r,rt<<1|1,v,h);    PushUp(rt,h);}void dfs(int u){    int lbg,lsm,rbg,rsm;    int sz=querys[u].size();    Node tmp;    for(int i=0;i<sz;++i)    {        tmp=querys[u][i];        lsm=Query1(1,n,1,tmp.w,0);        rsm=Query1(1,n,1,tmp.w,1);        lbg=Query2(1,n,1,tmp.w,0);        rbg=Query2(1,n,1,tmp.w,1);        if(cnt-lsm-rsm-lbg-rbg>0)          ans1[tmp.u]=-1;        else        {            ans1[tmp.u]=rsm;            ans2[tmp.u]=lbg+rbg+(lsm+rsm)*3;        }    }    if(lson[u]<0) return ;    cnt++;    Update(rnk[u],1,n,1,ww[u],0);    dfs(lson[u]);    Update(rnk[u],1,n,1,-1,0);    Update(rnk[u],1,n,1,ww[u],1);    dfs(rson[u]);    Update(rnk[u],1,n,1,-1,1);    cnt--;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t;    scanf("%d",&t);    while(t--)    {        Init();        scanf("%d",&n);        for(int i=1;i<=n;++i)        {            scanf("%d",&ww[i]);            node[i].w=ww[i];            node[i].u=i;        }        sort(node+1,node+n+1);        for(int i=1;i<=n;++i)          rnk[node[i].u]=i;        scanf("%d",&m);        int u,a,b;        for(int i=0;i<m;++i)        {            scanf("%d%d%d",&u,&a,&b);            flag[a]=flag[b]=true;            lson[u]=a;rson[u]=b;        }        for(int i=1;i<=n;++i)           if(!flag[i]) {u=i;break;}        scanf("%d",&q);        Node tmp;        for(int i=0;i<q;++i)        {            scanf("%d%d",&a,&b);            tmp.u=i;tmp.w=b;            querys[a].push_back(tmp);        }        build(1,n,1);        lf=rn=cnt=0;        dfs(u);        for(int i=0;i<q;++i)        {            if(ans1[i]==-1)              printf("0\n");            else printf("%d %d\n",ans1[i],ans2[i]);        }    }    return 0;}


 

原创粉丝点击