P3834 【模板】可持久化线段树 2
链接
主席树板子题
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
struct node
{
int l , r ;
int cnt ;
}tr[N * 4 + N * 17 ] ;
int n , m ;
int a[N] ;
vector<int>nums;
int root[N] ;
int idx ;
int build(int l , int r )
{
int p = ++idx ;
if(l == r) {
return p ;
}
int mid = l + r >> 1 ;
tr[p].l = build(l , mid ) , tr[p].r = build(mid + 1 , r ) ;
return p ;
}
int find(int a ){
return lower_bound(nums.begin() , nums.end() , a ) - nums.begin() ;
}
int insert(int p, int l, int r , int k )
{
int q = ++idx ;
tr[q] = tr[p] ;
if(l == r )
{
tr[q].cnt ++ ;
return q;
}
int mid = l + r >> 1 ;
if(k <= mid ) tr[q].l = insert(tr[p].l , l , mid , k ) ;
else tr[q].r = insert(tr[p].r , mid + 1 , r , k ) ;
tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt ;
return q ;
}
int query(int q , int p , int l , int r , int k )
{
if(l == r ) return r ;
int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
int mid = l + r >> 1 ;
if(k <= cnt ) return query(tr[q].l , tr[p].l , l , mid , k ) ;
else return query(tr[q].r , tr[p].r , mid + 1 , r , k - cnt) ;
}
int main()
{
cin>>n>>m;
for(int i = 1 ; i <= n; i ++ ) cin>>a[i] ,nums.push_back(a[i]) ;
sort(nums.begin() , nums.end()) ;
nums.erase(unique(nums.begin(), nums.end() ) , nums.end()) ;
root[0] = build(0 , nums.size() - 1 ) ;
for(int i = 1 ; i <= n ; i ++ )
{
root[i] = insert(root[i - 1 ] , 0 , nums.size() - 1 , find(a[i]));
}
while(m -- )
{
int l , r , k ;
cin>>l>>r>>k;
cout<<nums[query(root[r] , root[l - 1 ] , 0 , nums.size() - 1 , k )] <<endl;
}
return 0 ;
}