经典例题汇总
给定N个数字,M个操作(1=<N,M <= 1e5)
操作可以分为以下三种
1 在序列末尾添加数字
2 查找序列中第k个数字
3 对序列进行排序
我们可以维护一颗Trie树,Trie树中是已经维护好了的有序的序列,那么再使用一个vector来存储数据(存放没有排序好的)
代码如下所示
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = (int)2e5 + 8;
int T,n,m;
int op,x;
vector<int> v;
struct Trie
{
struct node
{
int nx[2],cnt,val;
void init()
{
for(int i = 0;i <= 1;++i) nx[i] = -1;
cnt = 0;
val = -1;
}
}t[maxn * 32];
int tot,root;
int newnode()//建立一个新的结点,并且返回当前结点的数值
{
t[++tot].init();
return tot;
}
void init()//新根节点的数值就是这个的数值
{
tot = 0;
root = newnode();
}
void insert(int s)
{
//将数据放入tire树中
int now = root;
for(int i = 30;i >= 0;--i)
{
int v = s >> i & 1;
if(t[now].nx[v] == -1) t[now].nx[v] = newnode();
now = t[now].nx[v];
t[now].cnt++;
}
t[now].val = s;
}
int query(int s)
{
int now = root;
for(int i = 30;i >= 0;--i)
{
if(t[now].nx[0] && t[t[now].nx[0]].cnt >= s) now = t[now].nx[0];
else
{
if(t[now].nx[0]) s -= t[t[now].nx[0]].cnt;
now = t[now].nx[1];
}
}
return t[now].val;
}
}trie;
void solve()
{
trie.init();//注意初始化问题
scanf("%d",&n);
for(int i = 1;i <= n;++i)
{
int kk;
scanf("%d",&x);
v.emplace_back(x);
}
int pre = 0;//记录当前树存储的数字个数
scanf("%d",&m);
while(m--)
{
scanf("%d",&op);
if(op == 1)
{
scanf("%d",&x);
v.emplace_back(x);
}
else if(op == 2)
{
scanf("%d",&x);
if(x <= pre)
{
printf("%d\n",trie.query(x));
}
else printf("%d\n",v[x - pre - 1]);
}
else
{
for(auto f:v)
{
trie.insert(f);
}
pre += v.size();
v.clear();
}
}
}
int main()
{
T = 1;
while(T--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号