您的位置:首页 > 其它

POJ 2104 划分树模板题

2015-04-14 09:54 399 查看
给出n,m

n个数字

m次询问,每次询问(l,r)区间的第k小的数

划分树模板 mark一下

#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;

int a[100010],as[100010];
int tree[20][100010];// 记录第i层元素序列
int sum[20][100010];// 记录第i层的1~j划分到左子树的元素个数(包括j)

void build(int c,int l,int r)
{
int mid,i;
int lm; // 记录左区间共有多少个数=as{mid]
int lp; //  左区间的mark
int rp; //  右区间的mark

mid=(l+r)/2;
lm=mid-l+1;
lp=l;
rp=mid+1;
for (i=l;i<=mid;i++)
if (as[i]<as[mid])
lm--;//先假设左边的(mid - l + 1)个数都等于as[mid],然后把实际上小于as[mid]的减去
for (i=l;i<=r;i++)
{
if (i==l)
sum[c][i]=0;
else
sum[c][i]=sum[c][i-1];

if (tree[c][i]==as[mid])
{
if (lm)
{
lm--;
sum[c][i]++;
tree[c+1][lp++]=tree[c][i];
}
else
tree[c+1][rp++]=tree[c][i];
}
else
if (tree[c][i]<as[mid])
{
sum[c][i]++;
tree[c+1][lp++]=tree[c][i];
}
else
tree[c+1][rp++]=tree[c][i];
}
if (l==r) return ;
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)// 在l-r区间内的  ql-qr区间中的第K小的数
{
int s;//[l, ql)内将被划分到左子树的元素数目
int ss;//[ql, qr]内将被划分到左子树的元素数目
int mid=(l+r)/2;

if (l==r)
return tree[c][l];

if (l==ql)
{
s=0;
ss=sum[c][qr];
}
else
{
s=sum[c][ql-1];
ss=sum[c][qr]-s;
}

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-l+1+ql-s,mid-l+1+qr-s-ss,k-ss);
}

int main()
{
int n,m,i,l,r,k;
while (scanf("%d%d",&n,&m)!=EOF)
{
for (i=1;i<=n;i++)
{
scanf("%d",&a[i]);
tree[0][i]=as[i]=a[i];
}
sort(as+1,as+1+n);
build(0,1,n);
while (m--)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",query(0,1,n,l,r,k));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: