【每日一题】24.换个角度思考 (主席树)

补题链接:Here

算法相关文章:主席树

显然是可以离线之后fenwick维护。

因为不喜欢离线,所以直接主席树了。

每次找到对应区间,然后相当于就是区间sum的问题了。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = N * 40;
int n, m, rt[N], lc[M], rc[M], sum[M], cnt;
#define mid (l+r>>1)
void change (int l, int r, int &x, int y, int k) {
	sum[x = ++cnt] = sum[y] + 1, lc[x] = lc[y], rc[x] = rc[y];
	if (l == r)    return ;
	if (k <= mid)    change (l, mid, lc[x], lc[y], k);
	else    change (mid + 1, r, rc[x], rc[y], k);
}
int ask (int l, int r, int x, int y, int ql, int qr) {
	if (l == ql && r == qr)    return sum[y] - sum[x];
	if (qr <= mid)    return ask (l, mid, lc[x], lc[y], ql, qr);
	else if (ql > mid)    return ask (mid + 1, r, rc[x], rc[y], ql, qr);
	else return ask (l, mid, lc[x], lc[y], ql, mid) + ask (mid + 1, r, rc[x], rc[y], mid + 1, qr);
}
signed main() {
	cin >> n >> m;
	for (int i = 1, x; i <= n; i++)    scanf ("%d", &x), change (1, 1e5, rt[i], rt[i - 1], x);
	for (int i = 1, l, r, k; i <= m; i++)    scanf ("%d %d %d", &l, &r, &k), printf ("%d\n", ask (1, 1e5, rt[l - 1], rt[r], 1, k) );
	return 0;
}
posted @ 2021-05-13 20:23  RioTian  阅读(62)  评论(0编辑  收藏  举报