#include <cstdio> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <cstdlib> #include <cmath> #include <utility> #include <vector> #include <queue> #include <map> #include <set> #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)>(y)?(y):(x)) #define INF 0x3f3f3f3f #define N 100005 using namespace std; int a[N],b[N]; struct node { node *ch[2]; int r,v,s; node(int vv) { r=rand();//优先级 v=vv;//值 ch[0]=ch[1]=NULL; } void maintain() { s=1;//左右子树的节点数加一(本身一个节点) if(ch[0]) s+=ch[0]->s; if(ch[1]) s+=ch[1]->s; } }; int find(node *root,int s)//查找排名为s的节点值,即第s小 { int k=root->ch[0]==NULL?0:root->ch[0]->s; if(s==k+1) return root->v; else if(s<=k) return find(root->ch[0],s); return find(root->ch[1],s-k-1); } void rotate(node *&root,int d)//d为0代表左旋 { node *tmp=root->ch[d^1]; root->ch[d^1]=tmp->ch[d]; tmp->ch[d]=root; root->maintain();//注意先维护root,再维护tmp,因为之后tmp节点就相当于是root了,最后还是要赋给root的 tmp->maintain(); root=tmp; } void insert(node *&root,int v) { if(root==NULL) root=new node(v); else { int d=v<root->v?0:1;//左子树都比根节点小,右子树都比根节点大 insert(root->ch[d],v); if(root->ch[d]->r > root->r) rotate(root,d^1); } root->maintain(); } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) scanf("%d",&b[i]); node *root=NULL; int j=1; for(int i=1;i<=n;i++) { insert(root,a[i]); while(j<=m&&b[j]<=i) { int v=find(root,j); printf("%d\n",v); j++; } } } return 0; }
原文:https://www.cnblogs.com/pengwenbangBlog/p/13263263.html