Description
JZ拥有一个很大的野生动物园。这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子。这些狮子从北到南编号为1,2,3,…,N。每头狮子都有一个觅食能力值Ai,Ai越小觅食能力越强。饲养员西西决定对狮子进行M次投喂,每次投喂都选择一个区间[I,J],从中选取觅食能力值第K强的狮子进行投喂。值得注意的是,西西不愿意对某些区域进行过多的投喂,他认为这样有悖公平。因此西西的投喂区间是互不包含的(即区间[1,10]不会与[3,4]或[5,10]同时存在,但可以与[9,11]或[10,20]一起)。同一区间也只会出现一次。你的任务就是算出每次投喂后,食物被哪头狮子吃掉了。
Input
觅食能力值。(1<=能力值<=maxlongint)。此后M行,每行描述一次投喂。第t+2的三个数I,J,K表示在第t次投喂中,西西选择了区间[I,J]内觅食能力值第K强的狮子进行投喂。
Output
输出文件有M行,每行一个整数。第i行的整数表示在第i次投喂中吃到食物的狮子的觅食能力值。
Sample Input
7 2
1 5 2 6 3 7 4
1 5 3
2 7 1
Sample Output
3
2
Data Constraint
Hint
对于100%的数据,有1<=N<=100000,1<=M<=50000。
Solution
此题为主席树模板题。
注意要离散化。
Code1
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 100010
using namespace std;
int a[N],b[N],c[N],d[N],rt[N*30],tree[N*30],ls[N*30],rs[N*30];
int n,m,l,r,k,ans,tot=0,sz=0;
void qs(int l,int r){
int i=l,j=r,m=a[l];
while(i<=j){
while(a[i]<m) i++;
while(a[j]>m) j--;
if(i<=j){
swap(a[i],a[j]);
swap(b[i],b[j]);
i++;j--;
}
}
if(l<j) qs(l,j);
if(i<r) qs(i,r);
}
void build(int x1,int &x2,int l,int r,int k){
if(!x2) x2=++sz;
tree[x2]=tree[x1]+1;
if(l==r) return;
int mid=(l+r)>>1;
if(k<=mid){
rs[x2]=rs[x1];
build(ls[x1],ls[x2],l,mid,k);
}
else{
ls[x2]=ls[x1];
build(rs[x1],rs[x2],mid+1,r,k);
}
}
int find(int x1,int x2,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)>>1;
int lson=tree[ls[x2]]-tree[ls[x1]];
if(k<=lson) return find(ls[x1],ls[x2],l,mid,k);
else return find(rs[x1],rs[x2],mid+1,r,k-lson);
}
int main(){
freopen("zoo.in","r",stdin);
freopen("zoo.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=i;
}
qs(1,n);
for(int i=1;i<=n;i++){
if(a[i]!=a[i-1]) tot++;
c[b[i]]=tot;
d[tot]=a[i];
}
for(int i=0;i<=n;i++) build(rt[i-1],rt[i],0,tot,c[i]);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l,&r,&k);
ans=find(rt[l-1],rt[r],0,tot,k);
printf("%d\n",d[ans]);
}
return 0;
}
Code2
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=100500;
int read(int &n)
{
char ch=getchar();
while((ch!='-')&&((ch<'0')||(ch>'9')))ch=getchar();
int q=0,w=1;if(ch=='-')w=-1,ch=getchar();
while(ch>='0' && ch<='9')q=q*10+ch-48,ch=getchar();n=q*w;return n;
}
int m,n,ans;
int b[N],lsh[N],tot;
int root[N];
struct qqww{int l,r,s;}a[N*20];
bool PX(int q,int w){return b[q]<b[w];}
void add(int y,int &x,int l,int r,int l1)
{
a[x=++tot]=a[y],a[x].s++;
if(l==r)return;
int t=(l+r)/2;
if(l1<=t)add(a[y].l,a[x].l,l,t,l1);else add(a[y].r,a[x].r,t+1,r,l1);
}
int find(int y,int x,int l,int r,int l1)
{
if(l==r)return l;
int t=(l+r)/2;
if(a[a[x].l].s-a[a[y].l].s>=l1)return find(a[y].l,a[x].l,l,t,l1);
return find(a[y].r,a[x].r,t+1,r,l1-a[a[x].l].s+a[a[y].l].s);
}
int main()
{
int q,w,m1,k;
read(n),read(m1);
fo(i,1,n) read(b[i]),lsh[i]=i;
sort(lsh+1,lsh+1+n,PX);m=1;
fo(i,1,n)lsh[m]=b[w=lsh[i]],b[w]=b[w]!=b[lsh[i+1]]?m++:m;
m--;tot=0;
fo(i,1,n)add(root[i-1],root[i],1,m,b[i]);
fo(i,1,m1)read(q),read(w),read(k),printf("%d\n",lsh[find(root[q-1],root[w],1,m,k)]);
return 0;
}
作者:zsjzliziyang
QQ:1634151125
转载及修改请注明
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/81748317