1011. 【GDKOI2009模拟3】Zoo

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

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/81748317