• hdu4605


    两颗线段树,分别维护向左走向右走的情况

    线段树的结点维护区间有多少点被路径经过了

    离线读入所有询问,dfs遍历树的每一个结点,访问到v时解决对v的所有查询,在dfs过程中只需要维护根节点到v的链,线段树查询链上有多少结点值大于或小于询问的x,即能求出到达x的概率

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<stdio.h>
    #include<iostream>
    #include<stdlib.h>
    #include<string.h>
    /*
    类似二叉搜索树
    给定一颗n个结点的二叉树
    给定数值x,从root开始沿着二叉树往下搜索,分三种情况
    1.搜到叶子结点或者结点权值等于X,停止搜索
    2.搜到结点权值w<x,搜索左右儿子几率各为1/2
    3.w>=x,搜索左右儿子几率各为1/8,7/8
    问v点被搜索到的概率是多少
    
    两棵线段树保存向左走向右走的结果分布情况
    离线+dfs
    */
    #include<algorithm>
    #include<vector>
    #include<map>
    using namespace std;
    #define maxn 110000
    #define lmin 1
    #define rmax len
    #define lson l,(l+r)/2,rt<<1
    #define rson (l+r)/2+1,r,rt<<1|1
    #define root lmin,rmax,1
    #define now l,r,rt
    #define int_now int l,int r,int rt
    #define INF 999999999999
    #define LL long long
    #define mod 10007
    struct list
    {
        int father;
        int l,r;
        int w;
    }node[maxn];//树的结点
    vector<int>vec[maxn];//询问结点v的问题编号
    struct listt
    {
        int x,y;
        int v;
        int w;
    }qq[maxn];//询问
    map<int,int>mp;
    int len;
    int fs[maxn*2];//离散化后的权值
    int st=0;
    int sum[maxn*4][2];//两棵线段树
    void updata(int ll,int rr,int x,int leap,int_now)
    {
        if(ll>r||rr<l)return;
        if(ll<=l&&rr>=r)
        {
            sum[rt][leap]+=x;
            return;
        }
        updata(ll,rr,x,leap,lson);
        updata(ll,rr,x,leap,rson);
        sum[rt][leap]=sum[rt<<1][leap]+sum[rt<<1|1][leap];
    }
    int query(int ll,int rr,int leap,int_now)
    {
        if(ll>r||rr<l)return 0;
        if(ll<=l&&rr>=r)return sum[rt][leap];
        return query(ll,rr,leap,lson)+query(ll,rr,leap,rson);
    }
    void dfs(int x)
    {
        for(int i=0;i<vec[x].size();i++)//遍历结点x对应的每个询问
        {
            int bi=vec[x][i];
            int w=qq[bi].w;
            w=mp[w];
            int nm=query(w,w,0,root)+query(w,w,1,root);//nm只有在走不到x结点时才非0
            int ll=query(1,w-1,0,root);//root到x路径上结点权值小于w并且球向左走的点个数
            int lr=query(w+1,len,0,root);//root到x路径上结点权值大于w并且球向左走的点个数
            int rl=query(1,w-1,1,root);//root到x路径上结点权值小于w并且球向左走的点个数
            int rr=query(w+1,len,1,root);//root到x路径上结点权值小于w并且球向左走的点个数;
            if(nm!=0)continue;
            qq[bi].x=rl;
            qq[bi].y=(ll+rl)*3+lr+rr;
     
        }
        int id=mp[node[x].w];
        if(node[x].l!=0)
        {
            updata(id,id,1,0,root);//在向左走的线段树中更新当前结点的权值
            dfs(node[x].l);
            updata(id,id,-1,0,root);//回溯,取消本次更新
        }
        if(node[x].r!=0)
        {
            updata(id,id,1,1,root);
            dfs(node[x].r);
            updata(id,id,-1,1,root);
        }
    }
    int main()
    {
        int T,n,m,u,l,r;
        scanf("%d",&T);
        while(T--)
        {
            st=0;
            memset(sum,0,sizeof(sum));
            memset(node,0,sizeof(node));
            mp.clear();
            scanf("%d",&n);
            len=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&node[i].w);
                fs[++st]=node[i].w;
                vec[i].clear();
            }
            scanf("%d",&m);
            while(m--)
            {
                scanf("%d%d%d",&u,&l,&r);
                node[l].father=node[r].father=u;
                node[u].l=l;
                node[u].r=r;
            }
            node[1].father=-1;
            int q,v,ww;
            scanf("%d",&q);
            for(int i=1;i<=q;i++)
            {
                scanf("%d%d",&v,&ww);
                fs[++st]=ww;
                qq[i].v=v;
                qq[i].w=ww;
                qq[i].x=qq[i].y=-1;
                vec[v].push_back(i);
            }
            sort(fs+1,fs+st+1);
            len=0;
            fs[0]=-1;
            for(int i=1;i<=st;i++)
            {
                if(fs[i]!=fs[i-1])
                {
                    if(mp.find(fs[i])==mp.end())
                    {
                        mp[fs[i]]=++len;
                    }
                }
            }
            dfs(1);
            for(int i=1;i<=q;i++)
            {
                if(qq[i].x==-1)puts("0");
                else
                {
                    printf("%d %d
    ",qq[i].x,qq[i].y);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    字符流与字节流的区别
    向文件尾部追加内容
    Hashmap实现原理及扩容机制详解
    HashMap的put和get方法原理
    关于数字化工厂&智能工厂建设 IT 经验总结
    @所有人,网易数字+大会报名通道正式开启!
    WinForm程序打包1之快速入门
    解决安装.NET Framework不受信任的根证书
    Cannot resolve com.sun:tools:1.8.0 错误解决
    IDEA 2020报“java:程序包XXXX不存在”或“java:找不到符号”
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9903423.html
Copyright © 2020-2023  润新知