// 主席树 O(nlognlogn)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 200005
#define lc(x) tr[x].l
#define rc(x) tr[x].r
struct node{
int l,r,s; //s:节点值域中有多少个数
}tr[N*20];
int root[N],idx;
int n,m,a[N],b[N];
void insert(int x,int &y,int l,int r,int pos){
y=++idx; //开点
tr[y]=tr[x]; tr[y].s++;
if(l==r) return;
int m=l+r>>1;
if(pos<=m) insert(lc(x),lc(y),l,m,pos);
else insert(rc(x),rc(y),m+1,r,pos);
}
int query(int x,int y,int l,int r,int k){
if(l==r) return l;
int m=l+r>>1;
int s=tr[lc(y)].s-tr[lc(x)].s;
if(k<=s) return query(lc(x),lc(y),l,m,k);
else return query(rc(x),rc(y),m+1,r,k-s);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]); b[i]=a[i];
}
sort(b+1,b+n+1);
int bn=unique(b+1,b+n+1)-b-1; //去重后的个数
for(int i=1; i<=n; i++){
int id=lower_bound(b+1,b+bn+1,a[i])-b;//下标
insert(root[i-1],root[i],1,bn,id);
}
while(m--){
int l,r,k; scanf("%d%d%d",&l,&r,&k);
int id=query(root[l-1],root[r],1,bn,k);
printf("%d\n",b[id]);
}
}
#include<bits/stdc++.h>
#define int long long
#define ll long long
using namespace std;
const int maxn=2e5+5;
struct Node{
int l,r;
int cnt;
};
Node tree[maxn*40];
int root[maxn];
int idx=0;
vector<ll>nums,sorted;
int get_id(int x){
return lower_bound(sorted.begin(),sorted.end(),x)-sorted.begin()+1;
}
void init_dis(const vector<ll>&data){
nums=data;
sorted=nums;
sort(sorted.begin(),sorted.end());
sorted.erase(unique(sorted.begin(),sorted.end()),sorted.end());
}
int build (int l,int r){
int node=++idx;
tree[node].cnt=0;
if(l==r)return node;
int mid=(l+r)/2;
tree[node].l=build(l,mid);
tree[node].r=build(mid+1,r);
return node;
}
void insert(int x,int &y,int l,int r,int v){
y=++idx;
tree[y]=tree[x];
tree[y].cnt++;
if(l==r)return ;
int m=(l+r)/2;
if(v<=m){
insert(tree[x].l,tree[y].l,l,m,v);
}
else{
insert(tree[x].r,tree[y].r,m+1,r,v);
}
}
int query(int u,int v,int l,int r,int k){
if(l==r)return l;
int mid=(l+r)/2;
int cnt=tree[tree[v].l].cnt-tree[tree[u].l].cnt;
if(k<=cnt){
return query(tree[u].l,tree[v].l,l,mid,k);
}
else{
return query(tree[u].r,tree[v].r,mid+1,r,k-cnt);
}
}
void init(const vector<ll>& data){
init_dis(data);
root[0]=build(1,sorted.size());
for(int i=1;i<=data.size();i++){
int x=get_id(data[i-1]);
insert(root[i-1],root[i],1,sorted.size(),x);
}
}
ll solve(int l,int r,int k){
int order=query(root[l-1],root[r],1,sorted.size(),k);
return sorted[order-1];
}
signed main(){
int n,m;
cin>>n>>m;
vector<ll>data;
for(int i=1;i<=n;i++){
ll da;
cin>>da;
data.push_back(da);
}
init(data);
for(int i=1;i<=m;i++){
int l,r,k;
cin>>l>>r>>k;
ll ans=solve(l,r,k);
cout<<ans<<endl;
}
}
下面是维护数组修改元素的:
#include<bits/stdc++.h>
using namespace std;
struct Node{
int l,r;
int val;
};
const int maxn=1e6+5;
Node tree[40*maxn];
int root[maxn];
int idx=0;
int build(int l,int r,const vector<int>&arr){
int node=++idx;
if(l==r){
tree[node].val=arr[l-1];
return node;
}
int mid=(l+r)/2;
tree[node].l=build(l,mid,arr);
tree[node].r=build(mid+1,r,arr);
return node;
}
void update(int x,int &y,int l,int r,int pos,int v){
y=++idx;
tree[y]=tree[x];
if(l==r){
tree[y].val=v;
return ;
}
int m=(l+r)/2;
if(pos<=m){
update(tree[x].l,tree[y].l,l,m,pos,v);
}
else{
update(tree[x].r,tree[y].r,m+1,r,pos,v);
}
}
int query(int node,int l,int r,int pos){
if(l==r){
return tree[node].val;
}
int mid=(l+r)/2;
if(pos<=mid){
return query(tree[node].l,l,mid,pos);
}
else return query(tree[node].r,mid+1,r,pos);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin>>n>>m;
vector<int>arr(n);
for(int i=0;i<n;i++){
cin>>arr[i];
}
root[0]=build(1,n,arr);
int cv=0;
while(m--){
int v,op;
cin>>v>>op;
if(op==1){
int p,c;
cin>>p>>c;
cv++;
update(root[v],root[cv],1,n,p,c);
}
else{
int p;
cin>>p;
cv++;
int val=query(root[v],1,n,p);
cout<<val<<"\n";
root[cv]=root[v];
}
}
}