[codevs2573/洛谷P1801]黑匣子

题目描述:
我们使用黑匣子的一个简单模型。它能存放一个整数序列和一个特别的变量i。在初始时刻,黑匣子为空且i等于0。这个黑匣子能执行一系列的命令。有两类命令:
ADD(x):把元素x放入黑匣子;
GET:把i加1的同时,输出黑匣子内所有整数中第i小的数。牢记第i小的数是当黑匣子中的元素已非降序排序后位于第i位的元素。

现需要一个有效的算法处理给定的一系列命令。ADD和GET命令的总数至多个有30000个。定义ADD命令的个数为M个,GET命令的个数为N个。

1.A(1),A(2),…A(M):一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数。
2.u(1),u(2),…u(N):表示第u(j)个元素被放进了Blaek Box里后就出现一个GET命令。例如上面的例子中u=(l,2,6,6)。输入数据不用判错

输入格式:
第一行,两个整数,M,N。
第二行,M个整数,表示A(l)……A(M)。
第三行,N个整数,表示u(l)…u(N)。

输出格式:
输出Black Box根据命令串所得出的输出串,一个数字一行。

题解:第一种方法就是用平衡树硬解,很管用。
第二种方法:开左右两个堆,左堆为大根堆,右堆为小根堆(方便转移),一个变量KAF用于记录当前答案,维护这两个堆:1.左堆的所有元素都小于等于KAF; 2.右堆所有元素都大于等于KAF ; 3.左堆的元素数量维持在i-1。

第一种方法

#include
#include
#include
#include
#include
#include
#include
#define LiangJiaJun main
using namespace std;
int l[300004],r[300004],s[300004],w[300004],rnd[300004],sz=0;
int neta=0,n,m,root=0;
int a[300004],u[300004];
void update(int x){s[x]=s[l[x]]+s[r[x]]+1;}
void lturn(int &x){
     int t=r[x];
     r[x]=l[t];
     l[t]=x;
     s[t]=s[x];
     update(x);
     x=t;
}
void rturn(int &x){
     int t=l[x];
     l[x]=r[t];
     r[t]=x;
     s[t]=s[x];
     update(x);
     x=t;
}
void add(int &k,int x){
     if(k==0){
         k=++sz;w[k]=x;
         rnd[k]=rand();s[k]=1;return;
     }
     s[k]++;
     if(xif(rnd[k]>rnd[l[k]])rturn(k);
     }
     else {
         add(r[k],x);
         if(rnd[k]>rnd[r[k]])lturn(k);
     }
}
int find(int k,int x){
    if(x==0)return -1;
    if(x<=s[l[k]])return find(l[k],x);
    else if(x>s[l[k]]+1)return find(r[k],x-s[l[k]]-1);
    else return w[k];
}
int LiangJiaJun(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&u[i]);
    int p=1;
    for(int i=1;i<=m;i++){
        add(root,a[i]);
        while(i==u[p]){
            printf("%d\n",find(root,p));
            ++p;
        }
    }
    return 0;
}

第二种方法

#include
#include
#include
#include
#include
#define LiangJiaJun main
using namespace std;
priority_queue<int,vector<int>,less<int> >q1;
priority_queue<int,vector<int>,greater<int> >q2;
int n,m,a[200004],KAF,ok=-1,ep=0;
int g[200004];
void repute(){
     if(q2.empty()){
        ok=-1;
        q1.push(KAF);
        return;
     }
     while(q1.size()int LiangJiaJun(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=m;i++){
        int x;
        scanf("%d",&x);
        g[x]++;
    }
    for(int i=1;i<=n;i++){
        if(ok == -1){
            ok = 1;
            KAF = a[i];
        }
        else{
            if(a[i]else q2.push(a[i]);
        }
        if(!q1.empty()&&a[i]int x=q1.top();
            q1.pop();
            KAF=x;
            q1.push(a[i]);
        }
        while(g[i]--){
            printf("%d\n",KAF);
            ++ep;
            repute();
        }
    }
    return 0;
}

你可能感兴趣的:(-----------数据结构,平衡树,堆)