经典例题汇总

给定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;
}

  

posted @ 2021-11-15 14:05  Treasure-  阅读(50)  评论(0)    收藏  举报