划分树模板题,敲上模板就ok了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define MP make_pair
#define LL long long
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#define MID ((l+r)>>1)
const int maxn = 100100;
const int INF = 0x3f3f3f3f;
struct KthNumber
{
int a[maxn], s[maxn], t[20][maxn], num[20][maxn];
void init(int n)
{
for(int i = 1; i <= n; i ++)
{
scanf("%d", &a[i]);
s[i] = t[0][i] = a[i];
}
sort(s+1, s+n+1);
}
void Build(int c, int l, int r)
{
int lm = MID-l+1, lp = l, rp = MID+1;
for(int i = l; i <= MID; i ++)
lm -= s[i] < s[MID];
for(int i = l; i <= r; i ++)
{
if(i == l) num[c][i] = 0;
else num[c][i] = num[c][i - 1];
if(t[c][i] == s[MID])
{
if(lm)
{
lm --; num[c][i] ++;
t[c+1][lp++] = t[c][i];
}
else t[c+1][rp++] = t[c][i];
}
else if(t[c][i] < s[MID])
{
num[c][i] ++;
t[c+1][lp++] = t[c][i];
}
else t[c+1][rp++] = t[c][i];
}
if(l<r)
Build(c+1, l, MID), Build(c+1, MID+1, r);
}
int Query(int c, int l, int r, int ql, int qr, int k)
{
if(l == r) return t[c][l];
int s, ss;
if(l == ql) s = 0, ss = num[c][qr];
else s = num[c][ql-1], ss = num[c][qr]-num[c][ql-1];
if(k <= ss) return Query(c+1, l, MID, l+s, l+s+ss-1, k);
else return Query(c+1, MID+1, r, MID+1+ql-l-s, MID+1+qr-l-s-ss, k-ss);
}
}sol;
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
sol.init(n);
sol.Build(0, 1, n);
while(m --)
{
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", sol.Query(0, 1, n, l, r, k));
}
}
}
poj 2104 K-th Number(划分树模板),布布扣,bubuko.com
原文地址:http://blog.csdn.net/ok_again/article/details/25301269