Black Box平衡树
Description
Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is empty and i equals 0. This Black Box processes a sequence of commands (transactions). There are two types of transactions:
ADD (x): put element x into Black Box;
GET: increase i by 1 and give an i-minimum out of all integers containing in the Black Box. Keep in mind that i-minimum is a number located at i-th place after Black Box elements sorting by non- descending.
Let us examine a possible sequence of 11 transactions:
Example 1
It is required to work out an efficient algorithm which treats a given sequence of transactions. The maximum number of ADD and GET transactions: 30000 of each type.
Let us describe the sequence of transactions by two integer arrays:
1. A(1), A(2), ..., A(M): a sequence of elements which are being included into Black Box. A values are integers not exceeding 2 000 000 000 by their absolute value, M <= 30000. For the Example we have A=(3, 1, -4, 2, 8, -1000, 2).
2. u(1), u(2), ..., u(N): a sequence setting a number of elements which are being included into Black Box at the moment of first, second, ... and N-transaction GET. For the Example we have u=(1, 2, 6, 6).
The Black Box algorithm supposes that natural number sequence u(1), u(2), ..., u(N) is sorted in non-descending order, N <= M and for each p (1 <= p <= N) an inequality p <= u(p) <= M is valid. It follows from the fact that for the p-element of our u sequence we perform a GET transaction giving p-minimum number from our A(1), A(2), ..., A(u(p)) sequence.
ADD (x): put element x into Black Box;
GET: increase i by 1 and give an i-minimum out of all integers containing in the Black Box. Keep in mind that i-minimum is a number located at i-th place after Black Box elements sorting by non- descending.
Let us examine a possible sequence of 11 transactions:
Example 1
N Transaction i Black Box contents after transaction Answer
(elements are arranged by non-descending)
1 ADD(3) 0 3
2 GET 1 3 3
3 ADD(1) 1 1, 3
4 GET 2 1, 3 3
5 ADD(-4) 2 -4, 1, 3
6 ADD(2) 2 -4, 1, 2, 3
7 ADD(8) 2 -4, 1, 2, 3, 8
8 ADD(-1000) 2 -1000, -4, 1, 2, 3, 8
9 GET 3 -1000, -4, 1, 2, 3, 8 1
10 GET 4 -1000, -4, 1, 2, 3, 8 2
11 ADD(2) 4 -1000, -4, 1, 2, 2, 3, 8
It is required to work out an efficient algorithm which treats a given sequence of transactions. The maximum number of ADD and GET transactions: 30000 of each type.
Let us describe the sequence of transactions by two integer arrays:
1. A(1), A(2), ..., A(M): a sequence of elements which are being included into Black Box. A values are integers not exceeding 2 000 000 000 by their absolute value, M <= 30000. For the Example we have A=(3, 1, -4, 2, 8, -1000, 2).
2. u(1), u(2), ..., u(N): a sequence setting a number of elements which are being included into Black Box at the moment of first, second, ... and N-transaction GET. For the Example we have u=(1, 2, 6, 6).
The Black Box algorithm supposes that natural number sequence u(1), u(2), ..., u(N) is sorted in non-descending order, N <= M and for each p (1 <= p <= N) an inequality p <= u(p) <= M is valid. It follows from the fact that for the p-element of our u sequence we perform a GET transaction giving p-minimum number from our A(1), A(2), ..., A(u(p)) sequence.
Input
Input contains (in given order): M, N, A(1), A(2), ..., A(M), u(1), u(2), ..., u(N). All numbers are divided by spaces and (or) carriage return characters.
Output
Write to the output Black Box answers sequence for a given sequence of transactions, one number each line.
Sample Input
7 4 3 1 -4 2 8 -1000 2 1 2 6 6
Sample Output
3 3 1 2
#include <cstdio> #include <cstring> #include <cstdlib> #include<iostream> using namespace std; const int N = 30005; const int MOD = 2147483647; int a[N],u[N]; struct Node { int left; //左子树 int right; //右子树 int size; //大小 int val; //值 int key; //平衡种子 }tree[N]; int root,tot; int add(int val){ tot++; tree[tot].size = 1; tree[tot].val = val; tree[tot].key = rand(); tree[tot].left = 0; tree[tot].right = 0; return tot; } void update_root(int now){ int left,right; left = tree[now].left; right = tree[now].right; tree[now].size = tree[left].size + tree[right].size + 1; } //拆分(now原treap,a左子树,b右子树,val值) void split_new(int now, int &a, int &b, int val){ if(now == 0){ a = 0; b = 0; return; } if(tree[now].val <= val){//now左子树中的所有值都小于now, a = now; split_new(tree[now].right, tree[a].right, b, val); }else{ b = now; split_new(tree[now].left, a, tree[b].left, val); } update_root(now); }//按权值aplit // void merge_new(int &now, int a, int b){ if(a==0 || b==0){ now = a+b; return; }//某节点为空直接返回另一节点,合并结束 //按照key值合并(堆性质) if(tree[a].key<tree[b].key){ /** * a树key值小于b树,那么b树属于a树的后代,因为b树恒大于a树,那么b树一定属于a树的右后代, * a的左子树不变,直接赋给now,递归合并a的右子树和b */ now = a; merge_new(tree[now].right, tree[a].right, b);//b加到a的右后代上,a的右子树与y合并 }else{ //a的key值大于b树,b的左子树与a合并 now = b; merge_new(tree[now].left, a, tree[b].left); } update_root(now); } void find_new(int now, int rank){//找第k大 while (tree[tree[now].left].size+1 != rank){ if(tree[tree[now].left].size >= rank){ now = tree[now].left; }else{ rank -= tree[tree[now].left].size + 1; now = tree[now].right; } } printf("%d\n", tree[now].val); } void insert_new(int val){ int x,y,z; x = 0; y = 0; z = add(val); split_new(root, x, y, val); merge_new(x,x,z); merge_new(root, x, y); } void get_val(int rank){ find_new(root, rank); } void solve(){ int n,m,op,x,i; scanf("%d%d", &n,&m); memset(tree, 0, sizeof(tree)); add(MOD); root = 1; tree[root].size = 0; for(i=0;i<n;i++){ scanf("%d",&a[i]); } int k=0; for(int j=0;j<m;j++){ scanf("%d",&x); for(;k<x;k++){ insert_new(a[k]); } get_val(j+1); } } int main(){ solve(); return 0; }

浙公网安备 33010602011771号