可持续化线段树(主席树) 算法模板与图解
#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;
}
先挖个坑放代码,图解慢慢更新~~~~