题意:给一个数列a[1~n],有m个询问
每次询问 [l,r]中第k小的数
思路:划分树
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 #define MAXN 100001 8 struct node 9 { 10 int val[MAXN],num[MAXN]; 11 }tree[20]; 12 int n,m; 13 int sorted[MAXN],a[MAXN]; 14 void build(int t,int left,int right) 15 { 16 if(left==right) 17 return ; 18 int mid=(left+right)/2; 19 int i,k1=left-1,k2=mid; 20 for(i=left;i<=right;i++) 21 { 22 if(tree[t].val[i]<=sorted[mid]) 23 tree[t+1].val[++k1]=tree[t].val[i]; 24 else 25 tree[t+1].val[++k2]=tree[t].val[i]; 26 tree[t].num[i]=k1+1-left+tree[t].num[left-1]; 27 } 28 build(t+1,left,mid); 29 build(t+1,mid+1,right); 30 } 31 void search(int left,int right,int l,int r,int k,int t) 32 { 33 if(left==right) 34 { 35 printf("%d\n",tree[t].val[left]); 36 return ; 37 } 38 int mid=(left+right)/2; 39 int temp=tree[t].num[r]-tree[t].num[l-1]; 40 int x=tree[t].num[l-1]-tree[t].num[left-1]; 41 int y=tree[t].num[r]-tree[t].num[left-1]; 42 if(temp>=k) 43 { 44 search(left,mid,left+x,left+y-1,k,t+1); 45 } 46 else 47 { 48 search(mid+1,right,mid+l-left+1-x,mid+r-left+1-y,k-temp,t+1); 49 } 50 } 51 int main() 52 { 53 memset(tree,0,sizeof(tree)); 54 scanf("%d%d",&n,&m); 55 int i; 56 int x,y,z; 57 for(i=1;i<=n;i++) 58 { 59 scanf("%d",a+i); 60 sorted[i]=a[i]; 61 tree[1].val[i]=a[i]; 62 } 63 sort(sorted+1,sorted+n+1); 64 build(1,1,n); 65 for(i=1;i<=m;i++) 66 { 67 scanf("%d%d%d",&x,&y,&z); 68 search(1,n,x,y,z,1); 69 } 70 return 0; 71 }