题目意思很简单直接拿样例来解释吧
7 4
3 1 -4 2 8 -1000 2
1 2 6 6
输入 n = 7 m =4,然后第一行输入n个数,然后另一行输入m个数
index = 1
1:输出n个数中前1个数中的第Index(1)小值
index=2
2:输出n个数中前2个数中的第index(2)小值
index=3
6:输出n个数中前6个数中的第index(3)小值
index=4
6:输出n个数中前6个数中的第index(4)小值
输入保证m个数单调递增
我这里就直接上Treap的模板(主要是为了我以后复习用)
数组模拟版:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <ctime> using namespace std; #define LL long long const int N = 100005; struct Treap { //num表示当前节点孩子的个数 int data,fix,num,cnt; int l,r; } tree[N]; int size,root; void left_rat(int &x)//旋转之后x都会成为当前子树的根 { int y = tree[x].r; tree[x].r = tree[y].l; tree[y].l = x; x = y; y = tree[x].l; tree[y].num = tree[tree[y].l].num + tree[tree[y].r].num + tree[y].cnt; tree[x].num = tree[tree[x].l].num + tree[tree[x].r].num + tree[x].cnt; } void right_rat(int &x)//这里num的计算可以画图理解 { int y = tree[x].l; tree[x].num = tree[tree[x].r].num + tree[tree[y].r].num + tree[x].cnt; tree[y].num = tree[tree[y].l].num + tree[x].num + tree[y].cnt; tree[x].l = tree[y].r; tree[y].r = x; x = y; y = tree[x].l; tree[y].num = tree[tree[y].l].num + tree[tree[y].r].num + tree[y].cnt; tree[x].num = tree[tree[x].l].num + tree[tree[x].r].num + tree[x].cnt; } void insert(int &x,int data)//注意递归的时候父节点的tree[x].num也要++,开始的时候没有注意这个 { if(x == 0) //null { x = ++size;//增加一个节点 tree[x].data = data; tree[x].l = tree[x].r = 0; tree[x].num = 1; tree[x].cnt = 1; tree[x].fix = rand(); } else if(data < tree[x].data) { ++tree[x].num; insert(tree[x].l,data); if(tree[x].fix < tree[tree[x].l].fix) right_rat(x); } else if(data > tree[x].data) { ++tree[x].num; insert(tree[x].r,data); if(tree[x].fix < tree[tree[x].r].fix) left_rat(x); } else if(data == tree[x].data) { ++tree[x].cnt; ++tree[x].num; } } void remove(int &x,int data) //这里是直到x->cnt=1的时候才删除节点x,而不是不管x->cnt就直接删除,这里的删除操作没有验证过 { if(x == 0) return;//null else if(data < tree[x].data)//递归的时候也要tree[x].num-- { --tree[x].num; remove(tree[x].l,data); } else if(data > tree[x].data) { --tree[x].num; remove(tree[x].r,data); } else if(data == tree[x].data && tree[x].cnt > 1) { tree[x].cnt --; tree[x].num --; } else if(data == tree[x].data && tree[x].cnt == 1) { tree[x].cnt --; tree[x].num --; if(tree[x].l == 0 && tree[x].r == 0) x = 0; else if(tree[x].l == 0) x= tree[x].r; else if(tree[x].r == 0) x = tree[x].l; else { if(tree[tree[x].l].fix > tree[tree[x].r].fix) { right_rat(x);//先旋转,把要删的结点不断选到叶子处,然后再删除 remove(tree[x].r,data); } else { left_rat(x); remove(tree[x].l,data); } } } } int query(int &x,int k) { if(k < tree[tree[x].l].num + 1) return query(tree[x].l,k); else if(k > tree[tree[x].l].num + tree[x].cnt) return query(tree[x].r,k-(tree[tree[x].l].num + tree[x].cnt)); else return tree[x].data; } int a[30010]; int main() { int n,m,pos; srand(100); root = size = 0; scanf("%d %d",&n,&m); for(int i =1 ; i<= n ; i++) scanf("%d",&a[i]); int index = 0; for(int i = 0 ; i < m ; i ++) { scanf("%d",&pos); for(int j = index + 1 ; j <= pos ; j ++) insert(root,a[j]); // tree.inorder(tree.root); //cout<<endl; index = pos; printf("%d\n",query(root,i+1)); } return 0; }
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <map> #include <vector> #include <ctime> #include <queue> using namespace std; const int MAXN = ~0U>>1; class Treap { public: struct Item { int element,size,times,fix; Item *left,*right; Item(int e) : element(e),size(1),times(1),fix(rand()) {} inline int lsize() { return left?left->size:0; } inline int rsize() { return right?right->size:0; } }*root,*null; Treap() { null = new Item(MAXN); null->size = null->times = 0; null->fix = rand(); null->element = MAXN; root = null->left = null->right = null; } // left void ZAG(Item*& x) { Item *y = x->right; x->right = y->left; y->left = x; x = y; y = x->left; y->size = y->lsize() + y->rsize() + y->times; x->size = x->lsize() + x->rsize() + x->times; } // right void ZIG(Item*& x) { Item *y = x->left; x->size = y->rsize() + x->rsize() + x->times; y->size = y->lsize() + x->size + y->times; x->left = y->right; y->right = x; x = y; y = x->left; y->size = y->lsize() + y->rsize() + y->times; x->size = x->lsize() + x->rsize() + x->times; } // insert void Insert(Item*& x,int e) { if (x == null) { x = new Item(e); x->element = e; x->fix = rand(); x->times = x->size = 1; x->left = x->right = null; } else if (e < x->element) { x->size ++; Insert(x->left,e); if (x->left->fix < x->fix) ZIG(x); } else if (e > x->element) { x->size ++; Insert(x->right,e); if (x->right->fix < x->fix) ZAG(x); } else if(e ==x->element) { ++x->times; ++x->size; } } // remove void Remove(Item*& x,int e) { if (x == null) return; if (e < x->element)//递归的时候注意x->size-- { x->size --; Remove(x->left,e); } else if (e > x->element) { x->size --; Remove(x->right,e); } else if (e == x->element && x->times > 1) { x->times--; x->size--; } else if(x->element == e && x->times == 1) //当且仅当x->times==1 { x->times--; x->size --; if (x->left == null || x->right == null) { Item *y = x; x = (x->left != null)?x->left:x->right; delete y; } else { if (x->left->fix < x->right->fix) { ZIG(x); Remove(x->right,e); } else { ZAG(x); Remove(x->left,e); } } } } // find min int FindMin() { Item *x; for (x = root; x->left != null; x = x->left); return x->element; } //find max int FindMax() { Item *x; for (x = root; x->right != null; x = x->right); return x->element; } // Predecessor Item* Pred(Item* x,Item* y,int e) { if (x == null) return y; if (e < x->element) return Pred(x->left,y,e); return Pred(x->right,x,e); } // Successor Item* Succ(Item* x,Item* y,int e) { if (x == null) return y; if (e <= x->element) return Succ(x->left,x,e); return Succ(x->right,y,e); } // Select Item* Select(Item* x,int n) { if(n >= x->left->size + 1 && n <= x->left->size + x->times) return x; else if(n <= x->left->size) return Select(x->left,n); else return Select(x->right,n - x->left->size - x->times); } // Rank int Rank(Item* x,int e) { if (e < x->element) return Rank(x->left,e); else if (e > x->element) return Rank(x->right,e) + x->left->size + x->times; return x->left->size + 1; } int count(int e) { Item *p = Pred(root,null,e); Item *s = Succ(root,null,e); return min(abs(p->element - e),abs(s->element - e)); } int solve(Item *x,int n) { Item *t = Select(x,n); return t->element; } void inorder(Item *x) { if(x==null) return; else { inorder(x->left); cout<<x->element<<" "<<x->times<<" "<<x->size<<" "<<x->fix<<" "; inorder(x->right); } } }; int a[30010]; int main() { int n,m,pos; srand(100); scanf("%d %d",&n,&m); Treap tree; for(int i =1 ; i<= n ; i++) scanf("%d",&a[i]); int index = 0; for(int i = 0 ; i < m ; i ++) { scanf("%d",&pos); for(int j = index + 1 ; j <= pos ; j ++) tree.Insert(tree.root,a[j]); // tree.inorder(tree.root); //cout<<endl; index = pos; printf("%d\n",tree.solve(tree.root,i+1)); } return 0; }