zoukankan      html  css  js  c++  java
  • 数据结构--主席树

    可持久化线段树

    静态区间第 (k)

    给定 (n) 个整数构成的序列,将对于指定的闭区间查询其区间内的第 (k) 小值。

    权值线段树

    权值线段树就是对一个值域上值的个数进行维护的线段树。

    举个栗子,对于1,1,2,3,3,3,4,4。

    在权值线段树上如何求第k小的值?

    显然如果左子树的值大于k的话,那么答案就在左子树上,不然就在右子树上,而且是右子树第(k-左子树值)小。

    主席树

    我们对每个节点,都新建一颗权值线段树,不过我们保留一些不变的节点,只新建改变的了的节点。

    对于询问[L,R],每个root[i]节点所表示的值域都是[1,n],

    (t[t[R].l].sum-t[t[L-1].l].sum)表示的就是区间[L,R]内值域属于([1,{n over 2}])数的个数。

    如果这个数大于k,那么表示答案落在值域([1,{n over 2}]),不然就表示答案落在值域([{n over 2},n])

    下图表示的是先插入一个2,再插入一个3之后的主席树。

    code

    #include <bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pii pair<int,int>
    const int inf = 0x3f3f3f3f;
    const int maxn = 201110;
    const int M = 1e9+7;
    int n,m;
    
    int read()
    {
        int x=0;
        char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
        return x;
    }
    
    int a[maxn];
    vector<int> v;
    
    struct node
    {
        int l,r,sum;
    }t[maxn*40];
    
    int cnt,root[maxn];
    
    int getid(int x)        //离散化
    {
        return lower_bound(v.begin(),v.end(),x)-v.begin() + 1;
    }
    
    void insert(int l,int r,int pre,int &now,int p)         //当前插入的区间,pre表示要复制的点,now表示要创建的新节点
    {
        t[++cnt] = t[pre];
        now = cnt;
        t[now].sum++;
        int mid = (l+r)/2;
        if(l == r) return;
        if(p <= mid) insert(l,mid,t[pre].l,t[now].l,p);
        else insert(mid+1,r,t[pre].r,t[now].r,p);
    }
    
    int query(int l,int r,int L,int R,int k)
    {
        if(l == r) return l;
        int mid = (l+r)/2;
        int tmp = t[t[R].l].sum - t[t[L].l].sum;
        if(k <= tmp) return query(l,mid,t[L].l,t[R].l,k);
        else return query(mid+1,r,t[L].r,t[R].r,k-tmp);
    }
    
    signed main()
    {
    #ifdef ONLINE_JUDGE
    #else
        freopen("data.in", "r", stdin);
    #endif
        n = read(), m = read();
        for(int i = 1; i <= n; i++) 
        {
            v.push_back(a[i] = read());
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        int sz = v.size();
        for(int i = 1; i <= n; i++) 
        {
            insert(1,sz,root[i-1],root[i],getid(a[i]));
        }
        int l,r,k;
        while(m--)
        {
            l = read(), r = read(), k = read();
            printf("%d
    ",v[query(1,sz,root[l-1],root[r],k)-1]);
        }
        return 0;
    }
    
  • 相关阅读:
    MAC下配置PHP环境详解, Apache,MySQL数据库,vim
    xib和storyboard小谈,
    iOS中block运用
    IOS-UIDynamic
    ProtocolBuffers-3 For Objective C (2)-进阶
    ProtocolBuffers-3 For Objective C (1)-简单的使用
    12. UITextField
    11. KVC And KVO
    10.OC中retainCount返回值不准的原因
    9. 了解 Cocoa-百度百科
  • 原文地址:https://www.cnblogs.com/hezongdnf/p/12888336.html
Copyright © 2011-2022 走看看