10pts 求条 AC#1
查看原帖
10pts 求条 AC#1
533102
monodev楼主2024/2/24 14:36
#include <iostream>
#include <unordered_map>
#include <algorithm>
using namespace std;

const int maxn = 2e5 + 1;

long long a[maxn], b[maxn];
int tot;

struct treenode {
	int lc, rc;
	long long val;
	treenode operator = (treenode x){
		lc = x.lc;
		rc = x.rc;
		val = x.val;
		return *this;
	}
} tree[maxn * 32];
int root[maxn];
long long (*pfunc)(long long, long long);

int update(int pre, int pl, int pr, int x)  // 建一棵只有 nlogn 个节点的新线段树 
// pre 为上一棵线段树的节点,pl、pr 为当前区间的左右端点,x 表示有求第 k 小的数 
{
	int rt = ++tot;   // 动态开新的节点
	tree[rt].lc = tree[pre].lc;  
	tree[rt].rc = tree[pre].rc;   // 直接利用上一棵线段树的左右儿子 
	tree[rt].val = tree[pre].val + 1;   // 因为新加入了一个节点,所有要 + 1 
	int mid = (pl + pr) >> 1;
	if(pl < pr)    // 不是叶子节点 
	{
		if(x <= mid)  tree[rt].lc = update(tree[pre].lc, pl, mid, x);   // 第 k 小的数在左子树上 
		else  tree[rt].rc = update(tree[pre].rc, mid + 1, pr, x);   // 第 k 小的数在右子树上
	}
	return rt; 
}

int kthelement(int u, int v, int pl, int pr, int k)   // 查询 [u, v] 中的第 k 小的数 
{
	if(pl == pr)  return pl;   // 找到叶子节点,找到了答案,即 b[pl] 
	int x = tree[tree[v].lc].val - tree[tree[u].lc].val;
	int mid = (pl + pr) >> 1;
	if(x >= k)  return kthelement(tree[u].lc, tree[v].lc, pl, mid, k);
	else  return kthelement(tree[u].rc, tree[v].rc, mid + 1, pr, k - x);
}

unordered_map<long long, int> discrete;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int n, m;
	cin >> n >> m;
	for(int i = 0; i < n; ++ i){
		cin >> a[i];
		b[i] = a[i];
	}
	
	sort(a, a + n);	// 离散化
	int s = unique(a, a + n) - a;
	for(int i = 1; i <= s; ++ i)
		discrete[a[i - 1]] = i;
	
	for(int i = 1; i <= n; ++ i)
		root[i] = update(root[i - 1], 1, s, discrete[a[i - 1]]);
	
	for(int i = 0; i < m; ++ i){
		int l, r, k;
		cin >> l >> r >> k;
		cout << a[kthelement(root[l - 1], root[r], 1, s, k) - 1] << endl;
	}
}
2024/2/24 14:36
加载中...