权值线段树

  • 权值线段树维护的是桶,按值域开空间,维护的是个数。
  • 简单线段树维护的是信息,按个数可开空间,维护的是特定信息。
    普通线段树能解决区间最值和区间和问题
    权值线段树可以解决数列第k大/小的问题
    主席树能解决数列的子区间的第k大/小。

板子

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
int tr[N * 4];
int n;
int a[N], b[N];
int s;
void change(int u, int l, int r, int x) // 单点修改
{
	if (l == r)
	{
		tr[u]++;
		return;
	}
	int mid = (l + r) / 2;
	if (x <= mid)
		change(u * 2, l, mid, x);
	else
		change(u * 2 + 1, mid + 1, r, x);
	tr[u] = tr[u * 2 + 1] + tr[u * 2];
}
long long query(int u, int nl, int nr, int l, int r) // 区间查询
{
	if (nl >= l && nr <= r)
		return tr[u];
	int res = 0;
	int mid = (nr + nl) / 2;
	if (l <= mid)
		res += query(u * 2, nl, mid, l, r);
	if (mid < r)
		res += query(u * 2 + 1, mid + 1, nr, l, r);
	return res;
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		b[i] = a[i];
	}
	sort(b + 1, b + 1 + n); // 离散化
	for (int i = 1; i <= n; i++)
	{
		int id = lower_bound(b + 1, b + 1 + n, a[i]) - b;
		change(1, 1, n, id);
		cout << query(1, 1, n, id + 1, n) << endl;
	}
	return 0;
}
/*
6
4 3 3 2 2 1

0
1
1
3
3
5*/
posted @ 2025-02-25 15:31  流氓兔LMT  阅读(16)  评论(0)    收藏  举报