1. 程式人生 > >刷題記錄-luoguP1801 黑匣子_NOI導刊2010提高(06)

刷題記錄-luoguP1801 黑匣子_NOI導刊2010提高(06)

本題主要就是找第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; }