hdu 4605 Magic Ball Game

题意:给出一棵二叉树,树上每个节点都有一个权值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;
}


 

你可能感兴趣的:(数据结构)