题目意思很简单直接拿样例来解释吧
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;
}
这题可以用STL中的优先队列(最小堆和最大堆)维护来解决,可以去研究下。