救救孩子吧 QAQ , wa哭了, 就过了两个点 救救我救救我 Orz
查看原帖
救救孩子吧 QAQ , wa哭了, 就过了两个点 救救我救救我 Orz
657194
demaxiya楼主2022/10/22 21:12
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 2e5 + 10;
vector<int > b;
struct node
{
	int sum;//表示当前区间范围内的数出现了多少次。
	int l, r;//表示当前节点的左右儿子节点对应的节点下标。
}tr[N * 40];
int num = 0;//表示当前节点的空间用到了多少。
int root[N];//表示当当前版本对应的根节点的编号。
int a[N];
void pushup(int u)//用来用子节点的值来更新父节点的值。
{
	tr[u].sum = tr[tr[u].l].sum + tr[tr[u].r].sum;
}

int fed(int x)
{
	return lower_bound(b.begin(), b.end(), x) - b.begin()  + 1;
}

void build(int u, int l, int r)//建树。
{
	if (l == r)
	{
		tr[u].sum = 0;
	}
	else
	{
		int mid = l + r >> 1;
		tr[u].l = ++num;//类似于二叉树的空间的申请
		tr[u].r = ++num;//同二叉树的申请。
		build(tr[u].l, l, mid);
		build(tr[u].r, mid + 1, r);
	}
}
//插入操作。
void insert(int pre ,int u, int l, int r, int x)
{
	if (l == r)
	{
		tr[u].sum++;
	}
	else
	{
		tr[u] = tr[pre];
		int mid = l + r >> 1;

		if (x <= mid)
		{
			tr[u].l = ++num;
			insert(tr[pre].l, tr[u].l, l, mid , x);
		}
		else
		{
			tr[u].r = ++num;
			insert(tr[pre].r, tr[u].r, mid + 1, r, x);
		}
		pushup(u);
	}
}
//查询操作。
int query(int pre, int now, int l, int r, int k)
{
	if (l == r)return l;
	else
	{
		int mid = l + r >> 1;
		int ans1 = tr[tr[now].l].sum - tr[tr[pre].l].sum;
		if (ans1 >= k)return query(tr[pre].l, tr[now].l, l, mid, k);
		else return query(tr[pre].r, tr[now].r, mid + 1, r, k - ans1);
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n, m;
	cin >> n >> m;
	root[0] = 1;
	num++;
	build(1, 1, n);
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		b.push_back(a[i]);
	}

	sort(b.begin(), b.end());
	b.erase(unique(b.begin(), b.end()), b.end());


	for (int i = 1; i <= n; i++)
	{
		root[i] = ++num;
		insert(root[i - 1], root[i], 1, n, fed(a[i]));
	}
	int l, r, k;
	while (m--)
	{
		cin >> l >> r >> k;
		cout << b[query(root[l - 1], root[r], 1, n, k) - 1]<< endl;
	}
}
2022/10/22 21:12
加载中...