Lost Cows

link

题目大意

每次找到没有被询问过的第k小的数。共$n$个询问,答案不超过$n$。$(n\leq 10^5)$

试题分析

其实是一个线段树的板子,然后用一下主席树的思想就行。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int N=1000001;
int sum[N<<2],st[N<<2],kth[N<<2],n;
void build(int k,int l,int r){
    sum[k]=(r-l+1);
    if(l==r) return;
    int mid=l+r>>1;
    build(k<<1,l,mid),build(k<<1|1,mid+1,r);
    return;
}
int query(int k,int l,int r,int kth){
    if(l==r) return l;
    int mid=l+r>>1;
    if(sum[k<<1]>=kth) return query(k<<1,l,mid,kth);
    return query(k<<1|1,mid+1,r,kth-sum[k<<1]);
}
void add(int k,int l,int r,int x,int y,int w){
    sum[k]+=w;
    if(l==r) return;
    int mid=l+r>>1;
    if(x<=mid) add(k<<1,l,mid,x,y,w);
    if(mid<y) add(k<<1|1,mid+1,r,x,y,w);
    return;
}
int main(){
    n=read();kth[1]=1;
    for(int i=2;i<=n;i++) kth[i]=read()+1;
    build(1,1,n);
    for(int i=n;i>=1;i--){
        st[i]=query(1,1,n,kth[i]);
        add(1,1,n,st[i],st[i],-1);
    }
    for(int i=1;i<=n;i++) printf("%d\n",st[i]);
}
View Code

猜你喜欢

转载自www.cnblogs.com/si-rui-yang/p/10139916.html