可持续化线段树(主席树) 算法模板与图解

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#define lowbit(a) ((a)&(-a))
#define mid(a,b) ((a)+(b))/2
#define OUT freopen("out.txt","w",stdout)
#define mem(a,b) memset(a,b,sizeof (a))
#define DEBUG(a) cout << (a) << endl
#define IN freopen("in.txt","r",stdin)
#define IO ios::sync_with_stdio(false);\
        cin.tie(0);\
        cout.tie(0);
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f;
const ll mod = 1e9+7;
const int maxn = 2e5+10;
struct node
{
    int ls,rs;
    int sum;
} tree[maxn*20];

int n,q,tot,m;
int root[maxn];
int a[maxn],b[maxn];
void disc()
{
    int i;
    sort(b,b+n);
    m=unique(b,b+n)-b;
    for(i=0; i<n; ++i)
        a[i]=lower_bound(b,b+m,a[i])-b+1;
}
void _insert(int y,int &x,int l,int r,int p)
{
    x = ++tot;
    tree[x] = tree[y];
    tree[x].sum ++ ;
    if(l == r)
        return;
    if(p <= mid(l,r))
        _insert(tree[y].ls,tree[x].ls,l,mid(l,r),p);
    else
        _insert(tree[y].rs,tree[x].rs,mid(l,r)+1,r,p);
}

int query(int x,int y,int l,int r,int kth)
{
    if(l == r)
        return l;
    int delta = tree[tree[y].ls].sum - tree[tree[x].ls].sum;
    if(kth <= delta)
        return query(tree[x].ls,tree[y].ls,l,mid(l,r),kth);
    else
        return query(tree[x].rs,tree[y].rs,mid(l,r)+1,r,kth-delta);
}

int main()
{
    cin >> n >> q;
    int buf ;
    for(int i=0; i<n; i++)
    {
        cin >> a[i];
        b[i] = a[i];
    }
    disc();
    for(int i=1; i<=n; i++)
        _insert(root[i-1],root[i],1,m,a[i-1]);
    int l,r,kth;
    for(int i=0; i<q; i++)
    {
        cin >> l >> r >> kth;
        DEBUG(b[query(root[l-1],root[r],1,m,kth)-1]);
    }
    return 0;
}

先挖个坑放代码,图解慢慢更新~~~~

posted @ 2019-03-21 16:42  秃头大师  阅读(244)  评论(0编辑  收藏  举报