zoukankan      html  css  js  c++  java
  • [poj 2104]主席树+静态区间第k大

    题目链接:http://poj.org/problem?id=2104

    主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即可得到第k大(小)元素。

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    #define lson(i) node[i].lson
    #define rson(i) node[i].rson
    
    const int maxn=100005;
    int rt[maxn];
    
    struct Node
    {
        int lson,rson,val;
    }node[maxn*30];
    int tot;
    
    void push_up(int i)
    {
        node[i].val=node[lson(i)].val+node[rson(i)].val;
    }
    
    int build(int l,int r)
    {
        int i=++tot;
        if (l==r) node[i].val=0;
        else
        {
            int mid=(l+r)/2;
            lson(i)=build(l,mid);
            rson(i)=build(mid+1,r);
            push_up(i);
        }
        return i;
    }
    
    int rebuild(int k,int x,int i,int nowl,int nowr)
    {
        int th=++tot;
        lson(th)=lson(i);
        rson(th)=rson(i);
        node[th].val=node[i].val;
        if (nowl==nowr) node[th].val+=x;
        else
        {
            int mid=(nowl+nowr)/2;
            if (k<=mid) node[th].lson=rebuild(k,x,lson(i),nowl,mid);
            else node[th].rson=rebuild(k,x,rson(i),mid+1,nowr);
            push_up(th);
        }
        return th;
    }
    
    int query(int rt1,int rt2,int k,int nowl,int nowr)
    {
        if (nowl==nowr) return nowl;
        int left=node[lson(rt2)].val-node[lson(rt1)].val;
        int mid=(nowl+nowr)/2;
        if (left>=k) return query(lson(rt1),lson(rt2),k,nowl,mid);
        else return query(rson(rt1),rson(rt2),k-left,mid+1,nowr);
    }
    
    int a[maxn];
    vector<int> ls;
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        ls.clear();
        for (int i=1;i<=n;i++) ls.push_back(a[i]);
        sort(ls.begin(),ls.end());
        ls.erase(unique(ls.begin(),ls.end()),ls.end());
        rt[0]=build(1,n);
        for (int i=1;i<=n;i++)
        {
            int j=lower_bound(ls.begin(),ls.end(),a[i])-ls.begin();
            rt[i]=rebuild(j+1,1,rt[i-1],1,n);
        }
        for (int i=1;i<=m;i++)
        {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d
    ",ls[query(rt[l-1],rt[r],k,1,n)-1]);
        }
        return 0;
    }
  • 相关阅读:
    子类父类拥有同名的方法时……
    大道至简第六章阅读感想
    大道至简第五章阅读感想
    java中子类与基类变量间的赋值
    继承与接口的使用
    产生10个随机数求和及一些产生随机数相关知识
    【文件处理】xml 文件 SAX解析
    【文件处理】xml 文件 DOM解析
    【文件处理】RandomAccessFile
    【Directory】文件操作(初识文件操作二)
  • 原文地址:https://www.cnblogs.com/acmsong/p/7373784.html
Copyright © 2011-2022 走看看