求区间第k大数...昨天块状链表没过...今天正经的用划分树做下..
顺带一个划分树教程
tip: build那里我觉得 if (l==r) return;这句话写在最开始就好,事实上我这么写的也过了..不知道他为什么放到后边..
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int n,m;
int a[100010],b[100010];
int tree[20][100010];
int num[20][100010];
void build(int i,int l,int r) {
//printf("== %d %d %d\n",i,l,r);
if (l==r) return;
int t=(l+r)/2,e=t-l+1,j,pl=l,pr=t+1;
for (j=l;j<=t;j++) if (b[j]<b[t]) e--;
for (j=l;j<=r;j++) {
num[i][j]=(j==l)?0:num[i][j-1];
if (tree[i][j]<b[t]) {
num[i][j]++;
tree[i+1][pl++]=tree[i][j];
} else if (tree[i][j]>b[t]) {
tree[i+1][pr++]=tree[i][j];
} else if (e>0) {
e--;
tree[i+1][pl++]=tree[i][j];
num[i][j]++;
} else {
tree[i+1][pr++]=tree[i][j];
}
}
build(i+1,l,t);
build(i+1,t+1,r);
}
int get(int i,int l,int r,int ql,int qr,int k) {
if (l==r) return tree[i][l];
int t=(l+r)/2,s=(l==ql)?0:num[i][ql-1],ss=num[i][qr]-s;
if (k<=ss)
return get(i+1,l,t,l+s,l+s+ss-1,k);
else
return get(i+1,t+1,r,ql+t-l+1-s,qr+t-l+1-s-ss,k-ss);
}
int main() {
int x,y,z,i;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) {
scanf("%d",&a[i]);
tree[0][i]=b[i]=a[i];
}
sort(b+1,b+n+1);
build(0,1,n);
for (i=0;i<m;i++) {
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",get(0,1,n,x,y,z));
}
/*
for (i=0;i<5;i++) {
for (int j=1;j<=n;j++) printf("%d ",tree[i][j]);
printf("\n");
}
for (i=0;i<5;i++) {
for (int j=1;j<=n;j++) printf("%d ",num[i][j]);
printf("\n");
}
*/
return 0;
}