【转】POJ 2104 归并排序树+二分查找
1. 二分查找容易死循环,注意 (low+high+1 )/2 , 以及 mid = high-1 或者 mid = low+1
2. 最小或者最大等极限情况要做特殊处理
3.手工调试程序结束后一定要删除检测语句
思路: 用线段树记录归并排序的过程,那么
(1)可以在log(n)时间内查找到 任意数c 在区间(i,j)之间的 名次, 也就是区间内比c小的数的个数+1,
(2)从而我们可以通过二分x来找到在区间(i,j)排名为k的数,注意满足此条件的数可能不止一个,举例 区间数列为
{3, 7,7, 5} k=4
那么满足排名3为的数有5,6,7, 显然我们要找的是7
(1)过程的也需要二分查找,只需要记录比c小的数的个数就可以了
// algorihm: 
#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <string> 
#include <cctype> 
#include <queue> 
#include"stdio.h"
/* 
#include <list> 
#include <stack> 
#include <set> 
#include <map> 
#include <cmath> 
*/ 
using namespace std;
#define ma(a,b) (a)>(b)?(a):(b) 
#define mi(a,b) (a)<(b)?(a):(b) 
#define FF(i,a,b) for(int i=(a);i<=(b);i++) 
#define RR(i,b) for(int i=(0);i<(b);i++) 
#define clr(x) memset(x,0,sizeof(x)) 
#define pb push_back 
#define mp make_pair 
#define sz size() 
#define F first 
#define S second 
#define vv vector 
#define ii iterator 
/* 
#include <sstream> 
#include <iterator> 
#define ssm stringstream 
*/ 
#define cn continue 
#define br break 
typedef int type; 
const int ST = 0; 
#define out(x) cout << #x << "=" << x << endl 
template <class T> void show(T a, int n) { for (int i = ST; i < ST+n; i++) { cout<<a[i]<<' '; } cout<<endl; } 
template <class T> void show(T a, int r, int l) { for (int i = ST; i < ST+r; i++) show(a[i], l); cout<<endl; } 
const int N=110000; 
struct node 
{ 
int l,r; 
}; 
node seg[4*N]; 
int n, m; 
int a[N], b[25][N]; 
void build(int root, int x, int y, int dep) 
{ 
int len=y-x+1; 
int mid=(x+y)/2; 
seg[root].l = x; 
seg[root].r = y; 
if(len>1) 
{ 
build(root*2,x,mid, dep+1); 
build(root*2+1,mid+1,y, dep+1); 
int i=x, j=mid+1,k=x; 
while(i<=mid || j<=y) 
{ 
if(j>y || (i<=mid && b[dep+1][i]<=b[dep+1][j] ) ) 
{ 
b[dep][k++] = b[dep+1][i++]; 
} 
else 
{ 
b[dep][k++] = b[dep+1][j++]; 
} 
} 
} 
else 
{ 
b[dep][x] = a[x]; 
} 
}
int query(int root, int c, int x, int y, int dep) 
{ 
int len=seg[root].r-seg[root].l+1; 
int mid=(seg[root].l+seg[root].r)/2; 
if(x<=seg[root].l && y>=seg[root].r) 
{ 
int low=seg[root].l, high=seg[root].r, mid; 
if(c <= b[dep][low])return 0; 
if(c > b[dep][high])return len; 
while(low < high) 
{ 
mid = (low+high+1)/2; 
if(b[dep][mid] >= c) high=mid-1; 
else low=mid; 
} 
return low-seg[root].l+1; 
} 
else 
{ 
int ret=0; 
if(x<=mid)ret += query(root*2,c,x,y,dep+1); 
if(y>mid)ret += query(root*2+1,c,x,y,dep+1); 
return ret; 
} 
} 
int main() 
{ 
scanf("%d%d", &n, &m); 
for(int i=1;i<=n;i++) scanf("%d", &a[i]); 
build(1,1,n,1); 
//show(b[1], n+1); 
while(m--) 
{ 
int i, j, k, low, hig, mid, num; 
scanf("%d%d%d", &i, &j, &k); 
low = 1; 
hig = n; 
while(low < hig) 
{ 
mid = (low+hig+1)/2; // hint +1 
num = query(1, b[1][mid], i, j, 1); 
if(num >= k) hig = mid-1; 
else low=mid; 
} 
printf("%d\n", b[1][low]); 
} 
//system("pause");          
return 0; 
} 
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号