刷題記錄-luoguP1801 黑匣子_NOI導刊2010提高(06)
阿新 • • 發佈:2019-02-11
本題主要就是找第k小的數
可以建一棵二叉搜尋樹,設節點左子樹的個數為size,則有:
如果k==size+1,那麼顯然這個節點就是第k小的數
如果k<size+1,那麼k肯定在左子樹中,且為左子樹中第k小的數
如果k>size+1,那麼k肯定在右子樹中,且為右子樹中第k-1-size小的數。
**********************************
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#define MAXN 200005
using namespace std;
struct Node{
int val;
int lsize;
Node *lch,*rch;
};
int m,n;
int a[MAXN],u[MAXN],b[MAXN];
Node *root;
Node *insert(Node *p,int x){
if(p==NULL){
Node *q=new Node;
q->val=x;
q->lch=q->rch=NULL;
q->lsize=0;
return q;
}
else{
if(x< p->val){
p->lch=insert(p->lch,x);
p->lsize++;
}
else{
p->rch=insert(p->rch,x);
}
return p;
}
}
Node *find(Node *p,int k){
if(k== (p->lsize)+1){
return p;
}
else if(k< (p->lsize)+1){
return find(p->lch,k);
}
else{
return find(p->rch,k-1-(p->lsize));
}
}
intmain(){
// freopen("data.in","r",stdin);
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]);
b[u[i]]++;
}
int k=0;
for(int i=1;i<=m;i++){
root=insert(root,a[i]);
while(b[i]){
k++;
Node *ans=find(root,k);
printf("%d\n",ans->val);
b[i]--;
}
}
return 0;
}