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小的数的个数就可以了
- /*
- PROG:
- LANG: C++
- ID: heben991
- */
- // algorihm:
- #include <iostream>
- #include <algorithm>
- #include <vector>
- #include <string>
- #include <cctype>
- #include <queue>
- /*
- #include <list>
- #include <stack>
- #include <set>
- #include <map>
- #include <cmath>
- */
- usingnamespace 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
- typedefint type;
- constint 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; }
- constint 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]);
- }
- return 0;
- }