聽說劃分樹能解決的問題主席樹基本都能解決,感覺主席樹好理解又好寫(至少比那些亂七八糟的平衡樹親切多了),乾脆就不學劃分樹了qaq
%%%lljakfather所有題都是主席樹模板題
其實就是可持久化線段樹啦。
假如一個序列有n個數,有m次修改。
首先我們想一想最暴力的方法就是建m顆線段樹,雖然想想就心累,空間很難開的下。
然後發現有些節點其實是可以多次利用的,於是把兒子指針遷過去就行啦(然而我不會指針)
表示不會利用STL
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int n,m;
int root[maxn],arr[maxn],b[maxn],tot=0,sz;
int aa,ff;char cc;
int read() {
aa=0;ff=1;cc=getchar();
while((cc<'0'|cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
struct Node{
int l,r,lson,rson,sum;
}node[20*maxn];
void bld(int pos,int last,int l,int r,int x) {
node[pos].l=l;node[pos].r=r;
node[pos].sum=node[last].sum+1;
if(l==r) return;
int mid=(l+r)>>1;
if(x<=b[mid]) {
node[pos].rson=node[last].rson;
bld(node[pos].lson=++tot,node[last].lson,l,mid,x);
}
else {
node[pos].lson=node[last].lson;
bld(node[pos].rson=++tot,node[last].rson,mid+1,r,x);
}
}
int q(int pos1,int pos2,int k) {
if(node[pos2].l==node[pos2].r) return node[pos2].l;
if(k<=node[node[pos2].lson].sum-node[node[pos1].lson].sum) return q(node[pos1].lson,node[pos2].lson,k);
k-=node[node[pos2].lson].sum-node[node[pos1].lson].sum;
return q(node[pos1].rson,node[pos2].rson,k);
}
int main() {
n=read();m=read();
for(int i=1;i<=n;++i) arr[i]=b[i]=read();
sort(b+1,b+n+1);sz=n;
root[0]=++tot;
for(int i=1;i<=n;++i) {
root[i]=++tot;
bld(tot,root[i-1],1,sz,arr[i]);
}
int x,y,z;
for(int i=1;i<=m;++i) {
x=read();y=read();z=read();
printf("%d\n",b[q(root[x-1],root[y],z)]);
}
return 0;
}