zoukankan      html  css  js  c++  java
  • BZOJ1803Spoj1487 Query on a tree III——主席树

    题目大意

      给一棵有点权的n个点的有根树,保证任意两点的点权不同,m次询问每次询问x的子树中权值第k大的点。

    输入

      先输入n,然后每个点点权,再输入n-1行每行两个数x,y代表x和y相连,再输入m,之后m次询问,每行两个数x,k。

      主席树,随便找一个点为根,再dfs出树的dfs序,按dfs序建每一时刻主席树,利用主席树查询x子树区间第k大。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    inline char _read()
    {
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=_read();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=_read();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=_read();}
        return x*f;
    }
    int n,m;
    int x,y;
    int tot;
    int num;
    int cnt;
    int q[100010];
    int s[100010];
    int t[100010];
    int v[100010];
    int to[200010];
    int ls[4000010];
    int rs[4000010];
    int next[200010];
    int head[100010];
    int root[100010];
    int sum[4000010];
    map<int,int>b;
    void add(int x,int y)
    {
        tot++;
        next[tot]=head[x];
        head[x]=tot;
        to[tot]=y;
    }
    void dfs(int x,int fa)
    {
        s[x]=++num;
        q[num]=x;
        for(int i=head[x];i;i=next[i])
        {
            if(to[i]!=fa)
            {
                dfs(to[i],x);
            }
        }
        t[x]=num;
    }
    int updata(int pre,int l,int r,int v)
    {
        int rt=++cnt;
        if(l==r)
        {
            sum[rt]=sum[pre]+1;
            return rt;
        }
        ls[rt]=ls[pre];
        rs[rt]=rs[pre];
        sum[rt]=sum[pre]+1;
        int mid=(l+r)>>1;
        if(v<=mid)
        {
            ls[rt]=updata(ls[pre],l,mid,v);
        }
        else
        {
            rs[rt]=updata(rs[pre],mid+1,r,v);
        }
        return rt;
    }
    int query(int x,int y,int l,int r,int k)
    {
        if(l==r)
        {
            return b[l];
        }
        int val=sum[ls[y]]-sum[ls[x]];
        int mid=(l+r)>>1;
        if(val<k)
        {
            return query(rs[x],rs[y],mid+1,r,k-val);
        }
        else
        {
            return query(ls[x],ls[y],l,mid,k);
        }
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            v[i]=read();
            b[v[i]]=i;
        }
        for(int i=1;i<n;i++)
        {
            x=read();
            y=read();
            add(x,y);
            add(y,x);
        }
        dfs(1,0);
        for(int i=1;i<=num;i++)
        {
            root[i]=updata(root[i-1],0,1e9,v[q[i]]);
        }
        m=read();
        for(int i=1;i<=m;i++)
        {
            x=read();
            y=read();
            printf("%d
    ",query(root[s[x]-1],root[t[x]],0,1e9,y));
        }
    }
  • 相关阅读:
    centos git编译
    Unix/Linux小计
    centos gcc编译
    c++隐式转换(implicit conversion)
    通用c程序Makefile
    对弈的Python学习笔记
    LeetCode最长回文子串
    JDBC09 CLOB文本大对象
    JDBC08时间处理
    JDBC07 事务
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9449809.html
Copyright © 2011-2022 走看看