主席树学习

求区间第k小

题目链接:https://www.luogu.org/problem/P3834

#include<bits/stdc++.h>

#define ll long long
#define ull unsigned long long
#define met(a, x) memset(a,x,sizeof(a))
#define inf 0x3f3f3f3f
#define Rint register int

using namespace std;
const ll mod = 1e9 + 7;
const int N = 2e5 + 10;
const int M = 3e6 + 10;
int a[N], b[N], c[N], cnt;
int sum[N << 5], L[N << 5], R[N << 5];

inline int build(int l, int r) {
    int rt = ++cnt;
    sum[rt] = 0;
    if (l < r) {
        int mid = (l + r) / 2;
        L[rt] = build(l, mid);
        R[rt] = build(mid + 1, r);
    }
    return rt;
}

inline int update(int pre, int l, int r, int x) {
    int rt = ++cnt;
    L[rt] = L[pre], R[rt] = R[pre], sum[rt] = sum[pre] + 1;
    if (l < r) {
        int mid = (l + r) / 2;
        if (x <= mid)L[rt] = update(L[pre], l, mid, x);
        else R[rt] = update(R[pre], mid + 1, r, x);
    }
    return rt;
}

inline int query(int u, int v, int l, int r, int k) {
    if (l >= r)return l;
    int x = sum[L[v]] - sum[L[u]];
    int mid = (l + r) / 2;
    if (x >= k)return query(L[u], L[v], l, mid, k);
    else return query(R[u], R[v], mid + 1, r, k - x);
}

int main() {
   // freopen("in","r",stdin);
//    freopen("out","w",stdout);
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(b + 1, b + 1 + n);
    int len = unique(b + 1, b + 1 + n) - (b + 1);
    c[0] = build(1, len);
    for (int i = 1; i <= n; i++) {
        int t = lower_bound(b + 1, b + 1 + len, a[i]) - b;
        c[i] = update(c[i - 1], 1, len, t);
    }
    while (m--) {
        int x, y, z;
        cin >> x >> y >> z;
        int t = query(c[x - 1], c[y], 1, len, z);
        cout << b[t] << endl;
    }
    return 0;
}

动态主席树,求区间第k小

题目链接:https://www.luogu.org/problem/P2617

可持久化数组

题目链接:https://www.luogu.org/problem/P3919

#include<bits/stdc++.h>
#define mid ((l+r)>>1)
using namespace std;
int rt[1000001],T[20000001],L[20000001],R[20000001];
int cnt;
int build(int l,int r)
{
    int root=++cnt;
    if(l==r)
    {
        scanf("%d",&T[root]);
        return root;
    }
    L[root]=build(l,mid);
    R[root]=build(mid+1,r);
    return root;
}
int update(int pre,int l,int r,int x,int c)
{
    int root=++cnt;
    if(l==r)
    {
        T[root]=c;
        return root;
    }
    L[root]=L[pre];
    R[root]=R[pre];
    if(x<=mid)L[root]=update(L[pre],l,mid,x,c);
    else R[root]=update(R[pre],mid+1,r,x,c);
    return root;
}
void query(int pre,int l,int r,int x)
{
    if(l==r)
    {
        printf("%d\n",T[pre]);
        return;
    }
    if(x<=mid)query(L[pre],l,mid,x);
    else query(R[pre],mid+1,r,x);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int v,cd,x,y;
    rt[0]= build(1,n);
    for(int i=1; i<=m; ++i)
    {
        scanf("%d%d%d",&v,&cd,&x);
        if(cd==1)
        {
            scanf("%d",&y);
            rt[i]= update( rt[v],1,n,x,y);
        }
        if(cd==2)
        {
            rt[i]= rt[v];
            query( rt[v],1,n,x);
        }
    }
    return 0;
}

 

posted @ 2019-08-27 21:34  oc_co  阅读(152)  评论(4)    收藏  举报