您的位置:首页 > 其它

[POJ2104] K-th Number(区间K小数,主席树模板)

2016-07-14 10:47 489 查看

Description

给N个数,M个询问区间k小值

Solution

显然可以用主席树维护,不解释。

注意要离散化

啊?主席树是什么?看这里

Code

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define MAXN 100005
using namespace std;
struct node
{
int ls,rs,sm;
}tr[20*MAXN];
struct number
{
int x,y;
}b[MAXN];
bool cmp(number x,number y)
{
return x.x<y.x;
}
int rt[MAXN],a[MAXN],n,m,num,nd,pt[MAXN];
void build(int lst,int now,int l,int r,int v)
{
if (l==r)
{
tr[now].sm=tr[lst].sm+1;
return;
}
int mid=(l+r)/2;
if (v<=mid)
{
tr[now].rs=tr[lst].rs;
tr[now].ls=++nd;
build(tr[lst].ls,nd,l,mid,v);
}
else
{
tr[now].ls=tr[lst].ls;
tr[now].rs=++nd;
build(tr[lst].rs,nd,mid+1,r,v);
}
tr[now].sm=tr[tr[now].ls].sm+tr[tr[now].rs].sm;
}
int find(int lst,int now,int l,int r,int v)
{
if (l==r) return l;
int mid=(l+r)/2;
int ls1=tr[lst].ls,ls2=tr[now].ls,sum=tr[ls2].sm-tr[ls1].sm;
if (sum<v) return find(tr[lst].rs,tr[now].rs,mid+1,r,v-sum);
else return find(tr[lst].ls,tr[now].ls,l,mid,v);
}
int main()
{
cin>>n>>m;
int i,j;
num=0,nd=0;
fo(i,1,n)
{
scanf("%d",&a[i]);
b[i].x=a[i];
b[i].y=i;
}
sort(b+1,b+n+1,cmp);
fo(i,1,n)
{
if (b[i].x!=b[i-1].x) num++;
pt[num]=b[i].x;
a[b[i].y]=num;
}
fo(i,1,n)
{
rt[i]=++nd;
build(rt[i-1],rt[i],1,n,a[i]);
}
fo(i,1,m)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
printf("%d\n",pt[find(rt[x-1],rt[y],1,n,k)]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: