POJ 2104

划分树。

具体划分树算法可以参考下面总结:

划分树算法总结

但上面的算法代码有点错误,可以看我的代码下面指出

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N=100050;
int sorted[N];
struct node{
	int val[N];
	int num[N];
}tp[30];
int n,m;

void build(int lft,int rht,int p){
	if(lft==rht) return ;
	int i,mid=(lft+rht)/2;
	int isame=mid-lft+1,same=0;
	for(i=lft;i<=rht;i++){
		if(tp[p].val[i]<sorted[mid]) isame--;
	}
	int ln=lft,rn=mid+1;
	for(i = lft; i <= rht; i++) {
		if(i == lft) { 
			tp[p].num[i] = 0;
		} else {
			tp[p].num[i] = tp[p].num[i-1];
		}
		if(tp[p].val[i] < sorted[mid]) {
			tp[p].num[i]++;
			tp[p+1].val[ln++] = tp[p].val[i];
		}else if(tp[p].val[i] > sorted[mid]) {
			tp[p+1].val[rn++] = tp[p].val[i];
		}else {
			if(same < isame) {
				same++; 
				tp[p].num[i]++;
				tp[p+1].val[ln++] = tp[p].val[i];
			}else {
				tp[p+1].val[rn++] = tp[p].val[i];
			}
		}
	}
	build(lft, mid, p+1);
	build(mid+1, rht, p+1);
}

int query(int a, int b, int k, int p, int lft, int rht) {
	if(lft == rht) return tp[p].val[a]; 
	int s, ss, b2, bb, mid = (lft+rht)/2;
	if(a == lft) { 
		s = tp[p].num[b]; 
		ss = 0;
	} else {
		s = tp[p].num[b] - tp[p].num[a-1];
		ss = tp[p].num[a-1];
	}
	if(s >= k) {
		a = lft + ss; 
		b = lft + ss + s - 1;
		return query(a, b, k, p+1, lft, mid);
	} else {
		bb = a - lft - ss;
		b2 = b - a + 1 - s;    //这里应该是加1
		a = mid + bb + 1;
		b = mid + bb + b2;
		return query(a, b, k-s,p+1, mid+1, rht);
	}
}

int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		for(int i=1;i<=n;i++){
			scanf("%d",&tp[0].val[i]);
			sorted[i]=tp[0].val[i];
		}
		sort(sorted+1,sorted+1+n);
		build(1,n,0);
		int l,r,k;
		for(int i=1;i<=m;i++){
			scanf("%d%d%d",&l,&r,&k);
			printf("%d\n",query(l,r,k,0,1,n));
		}
	}
	return 0;
}    

  

posted @ 2015-04-06 21:31  chenjunjie1994  阅读(131)  评论(0编辑  收藏  举报