题目:http://poj.org/problem?id=2761
题意:有n个数,给m个区间,求这m个区间的地K大值
思路:裸划分树,与2104相同~~
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100000;
int n, m, a, b, c;
int sorted[maxn+10], array[40][maxn+10], num[40][maxn+10];
void BuildTree(int v, int left, int right)
{
if (left==right) return;
int mid=(left+right)>>1;
int lchild=left, rchild=mid+1;
int isame=mid-left+1, same=0;
for (int i=left; i<=right; i++) if (array[v][i]<sorted[mid]) isame--;
for (int i=left; i<=right; i++)
{
if (i==left) num[v][i]=0;
else num[v][i]=num[v][i-1];
if (array[v][i]<sorted[mid])
{
num[v][i]++;
array[v+1][lchild++]=array[v][i];
}
else if (array[v][i]>sorted[mid]) array[v+1][rchild++]=array[v][i];
else
{
if (same<isame)
{
same++;
num[v][i]++;
array[v+1][lchild++]=array[v][i];
}
else array[v+1][rchild++]=array[v][i];
}
}
BuildTree(v+1, left, mid);
BuildTree(v+1, mid+1, right);
}
int Query(int l, int r, int k, int v, int left, int right)
{
if (left==right) return array[v][l];
int mid=(left+right)>>1;
int s, ss, b, bb;
if (l==left)
{
s=num[v][r];
ss=0;
}
else
{
s=num[v][r]-num[v][l-1];
ss=num[v][l-1];
}
if (s>=k)
{
l=left+ss;
r=left+ss+s-1;
return Query(l, r, k, v+1, left, mid);
}
else
{
b=l-left-ss;
bb=r-l-s+1;
l=mid+b+1;
r=mid+b+bb;
return Query(l, r, k-s, v+1, mid+1, right);
}
}
int main()
{
//freopen("in.txt", "r", stdin);
while (scanf("%d %d", &n, &m)==2)
{
for (int i=1; i<=n; i++)
{
scanf("%d", &sorted[i]);
array[1][i]=sorted[i];
}
sort(sorted+1, sorted+1+n);
BuildTree(1, 1, n);
for (int i=0; i<m; i++)
{
scanf("%d %d %d", &a, &b, &c);
printf("%d\n", Query(a, b, c, 1, 1, n));
}
}
return 0;
}
PKU 2761 Feed the dogs
最新推荐文章于 2021-02-27 12:08:25 发布
本文介绍如何使用裸划分树解决给定区间内的第K大元素查询问题,通过构建树形结构,实现高效的区间查询。


400

被折叠的 条评论
为什么被折叠?



