K-th number

来源:互联网 发布:ug零件产品编程教程 编辑:程序博客网 时间:2024/06/06 06:39
  • 归并树
  • 划分树
  • 分块
目前只看会了第一种,在POJ - 2104上跑了接近4s,POJ - 2761直接超时。
发现自己的二分....真的水
归并树:
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int maxn = 1e5 + 10;const int inf = 0x3f3f3f3f;int n,m;int data[maxn];   //初始数据int d[20][maxn];  //线段树void build(int deep,int l,int r)    //O(n) 按升序排列的{    if(l == r)  { d[deep][l] = data[l] ; return;}    int mid = l + r >> 1;    build(deep+1, l ,  mid);    build(deep+1, mid+1, r);    //归并排序合并的过程    int tid = l,i = l, j = mid + 1;    while(i <= mid && j <= r)    {        if(d[deep+1][i] < d[deep+1][j]) d[deep][tid++] = d[deep+1][i++];        else d[deep][tid++] = d[deep+1][j++];    }    while(i <= mid) d[deep][tid++] = d[deep+1][i++];    while(j <= r) d[deep][tid++] = d[deep+1][j++];}int query(int ql,int qr,int val,int l,int r,int deep){    if( r < ql || l > qr) return 0;    if( ql <= l && r <= qr)    {        int num = upper_bound(d[deep] + l, d[deep] + r + 1,val) - (d[deep] + l);        return num;    }    int mid = l+r>>1;    int ans = 0;    if(ql <= mid)  ans += query(ql, qr, val, l , mid, deep+1);    if(qr >  mid)  ans += query(ql, qr, val, mid+1 , r, deep+1);    return ans;}int solve(int ql,int qr,int k){    int l = -inf,r = inf,ans = 0;    while(l <= r)    {        int mid = l + (r-l)/2;        int num = query(ql, qr, mid, 1 , n , 0);        if(num >= k) ans = mid,r = mid-1;        else l = mid+1;    }    return ans;}void init(){    memset(d,0,sizeof(d));}int main(){    int a,b,c;    while(~scanf("%d%d",&n,&m))    {        init();        for(int i = 1; i <= n; i++) scanf("%d",&data[i]);        build(0,1,n);    //建树        for(int i = 0; i < m; i++)        {            scanf("%d%d%d",&a,&b,&c);            if(a > b) swap(a,b);            int ans = solve(a,b,c);            printf("%d\n",ans);        }    }return 0;}