題目連結:http://poj.org/problem?id=2761
代碼風格:notonlysuccess劃分樹http://www.notonlysuccess.com/index.php/divide-tree/
上面的網站對劃分樹有相當詳細的說明~~不再贅述
題目大意: 有n隻小狗,每個小狗有一個相對的魅力值,求第i隻小狗~第j隻小狗中魅力值第k大的那個小狗的魅力值是多少(即求區間[i, j]第k大的數)
直接附上代碼:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define mid int m = (l+r) >> 1
struct nod
{
int l, r;
}p[1345678];
int val[20][200002];
int w[1898989];
int tol[20][200020];
void build(int l, int r, int rt, int ss)
{
p[rt].l = l;
p[rt].r = r;
if(l == r)
return ;
mid ;
int lsame = m - l + 1;
int i;
for(i = l; i <= r; i ++)
if(val[ss][i] < w[m])
lsame --;
int lpos = l ;
int rpos = m+1;
int same = 1;
for(i = l; i <= r; i ++)
{
if(l == i)
tol[ss][i] = 0;
else tol[ss][i] = tol[ss][i-1];
if(val[ss][i] < w[m])
{
tol[ss][i] ++;
val[ss+1][lpos ++] = val[ss][i];
}
else if(val[ss][i] > w[m])
{
val[ss+1][rpos ++] = val[ss][i];
}
else
{
if(same <= lsame)
{
tol[ss][i] ++;
val[ss+1][lpos ++] = val[ss][i];
same ++;
}
else {
val[ss+1][rpos ++] = val[ss][i];
}
}
}
build(lson, ss+1);
build(rson, ss+1);
}
int query(int k, int l, int r, int rt, int d)
{
if(l == r)
return val[d][l];
int s, ss;
if(l == p[rt].l )
{
s = tol[d][r];
ss = 0;
}
else {
s = tol[d][r] - tol[d][l-1];
ss = tol[d][l-1];
}
if(k <= s)
{
int newl = ss + p[rt].l;
int newr = ss + p[rt].l + s - 1;
return query(k, newl, newr, rt << 1, d+1);
}
else
{
int b = r-l+1-s;
int bb = l - p[rt].l - ss;
int m = (p[rt].l + p[rt].r ) >> 1;
int newl = bb + m + 1;
int newr = bb + m + b;
return query(k-s, newl, newr, rt << 1 | 1, d + 1);
}
}
int main()
{
int n, m;
int a, b, c;
while(scanf("%d%d", &n, &m) != EOF)
{
int i;
for(i = 1; i <= n; i ++)
{
scanf("%d", &w[i]);
val[0][i] = w[i];
}
sort(w+1, w+n+1);
build(1, n, 1, 0);
while(m --)
{
scanf("%d%d%d", &a, &b, &c);
int k ;
if(a <= b)
k = query(c, a, b, 1, 0);
else k = query(c, b, a, 1, 0);
printf("%d\n", k);
}
}
return 0;
}