zoukankan      html  css  js  c++  java
  • hdu 4605 线段树与二叉树遍历

    思路:

    首先将所有的查询有一个vector保存起来。我们从1号点开始dfs这颗二叉树,用线段树记录到当前节点时,走左节点的有多少比要查询该节点的X值小的,有多少大的,

    同样要记录走右节点的有多少比X小的,多少比X大的。小和大的x,y值题目给了。当要进行左儿子时,建该节点值插入走左的线段树,回退的时候将其删除,进入右儿子时将其插入走右的线段树,同样回退时删除。遍历完一个树,整个查询就做完了,最后输出。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #define Maxn 200100
    #define lson(x) (x<<1)
    #define rson(x) ((x<<1)+1)
    #define mid ((tree[po].l+tree[po].r)>>1)
    #define inf 100000000
    using namespace std;
    struct Query{
        int x,i;
    };
    struct AA{
        int x,y;
    }ans[Maxn];
    struct Tree{
        int l,r,lnum,rnum;
    }tree[Maxn*20];
    int head[Maxn],e,w[Maxn],Index[Maxn],flag=0,L,R,Lsum,Rsum;
    vector<Query> query[Maxn];
    struct Edge{
        int u,v,next;
    }edge[Maxn];
    void buildTree(int l,int r,int po)
    {
        tree[po].l=l,tree[po].r=r;
        tree[po].lnum=0,tree[po].rnum=0;
        if(l==r)
            return ;
        buildTree(l,mid,lson(po));
        buildTree(mid+1,r,rson(po));
    }
    void Insert(int val,int po,int type)
    {
        if(tree[po].l==tree[po].r)
        {
            if(type)
                tree[po].rnum++;
            else
                tree[po].lnum++;
            return ;
        }
        if(type)
            tree[po].rnum++;
        else
            tree[po].lnum++;
        if(Index[mid]>=val)
            Insert(val,lson(po),type);
        else
            Insert(val,rson(po),type);
    }
    void del(int val,int po,int type)
    {
        if(tree[po].l==tree[po].r)
        {
            if(type)
                tree[po].rnum--;
            else
                tree[po].lnum--;
            return ;
        }
        if(type)
            tree[po].rnum--;
        else
            tree[po].lnum--;
        if(Index[mid]>=val)
            del(val,lson(po),type);
        else
            del(val,rson(po),type);
    }
    void get_Num(int val,int po)
    {
        if(Index[tree[po].l]>val)
            return ;
        if(Index[tree[po].r]<val)
        {
                R+=tree[po].rnum;
                L+=tree[po].lnum;
                return ;
        }
        if(tree[po].l==tree[po].r)
        {
            if(tree[po].rnum||tree[po].lnum)//如果图中有相同数值,则不能到达
                flag=1;
            return ;
        }
        get_Num(val,lson(po));
        get_Num(val,rson(po));
    }
    void init()
    {
        e=0;
        Lsum=Rsum=0;
        memset(head,-1,sizeof(head));
        for(int i=0;i<=110010;i++)
         {
             query[i].clear();
             ans[i].x=ans[i].y=0;
         }
    }
    void add(int u,int v)
    {
        edge[e].u=u;edge[e].v=v;edge[e].next=head[u];head[u]=e++;
    }
    void dfs(int u)//进行二叉树遍历
    {
        int i,j,temp,Size,pos;
        Size=query[u].size();
        for(i=0;i<Size;i++)
        {
            L=R=flag=0;
            get_Num(query[u][i].x,1);
            if(flag)
            {
                ans[query[u][i].i].y=-1;
                continue;
            }
            ans[query[u][i].i].y+=L*3;
            ans[query[u][i].i].y+=Lsum-L;
            ans[query[u][i].i].y+=R*3;
            ans[query[u][i].i].y+=Rsum-R;
            ans[query[u][i].i].x+=R;
        }
        int f=0;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            if(f)
            {
                Insert(w[u],1,1);
                Rsum++;
            }
            else
            {
                Insert(w[u],1,0);
                Lsum++;
            }
            f++;
            dfs(edge[i].v);
            if(f==2)
            {
                del(w[u],1,1);
                Rsum--;
            }
            else
            {
                del(w[u],1,0);
                Lsum--;
            }
        }
    }
    int main()
    {
        int n,m,q,t,i,j,a,b,u,num;
        scanf("%d",&t);
        while(t--)
        {
            init();
            num=0;
            scanf("%d",&n);
            for(i=1;i<=n;i++)
             {
                scanf("%d",w+i);
                Index[i]=w[i];
             }
            sort(Index+1,Index+n+1);
            num=1;
            for(i=2;i<=n;i++)//将坐标离散化
            if(Index[i]>Index[num])
                Index[++num]=Index[i];
            buildTree(1,num,1);//建立线段树
            scanf("%d",&m);
            for(i=1;i<=m;i++)
            {
                scanf("%d%d%d",&u,&a,&b);
                add(u,b);
                add(u,a);
            }
            scanf("%d",&q);
            Query temp;
            int v;
            for(i=1;i<=q;i++)//将所有查询保存起来
            {
                scanf("%d%d",&v,&temp.x);
                temp.i=i;
                query[v].push_back(temp);
            }
            int f=0;//标记走左还是右
            for(i=head[1];i!=-1;i=edge[i].next)//从1号节点开始遍历
            {
                if(f)//若走右
                {
                    Insert(w[1],1,1);//将该值插入右线段树,并且总数加1
                    Rsum++;
                }
                else
                {
                    Insert(w[1],1,0);//插入左线段树,总数加1
                    Lsum++;
                }
                    f++;
                dfs(edge[i].v);
                if(f==2)
                {
                    del(w[1],1,1);//从右儿子退出,将其删除,总数减1
                    Rsum--;
                }
                else
                {
                    del(w[1],1,0);//从左儿子退出
                    Lsum--;
                }
            }
            for(i=1;i<=q;i++)
            {
                if(ans[i].y!=-1)
                    printf("%d %d
    ",ans[i].x,ans[i].y);
                else
                    printf("0
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    贝叶斯公式推导
    三种常量池
    SpringCloud使用Feign实现服务间通信
    springCloud配置本地配中心SpringCloudConfig
    SpringApplication执行流程
    调用shutdown.sh后出现could not contact localhost8005 tomcat may not be running报错问题
    TCP协议详解
    web.xml配置说明
    第一份offer
    博客CSS
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3211077.html
Copyright © 2011-2022 走看看