洛谷P4559 [JSOI2018] 列队 题解 可持久化线段树
题目链接:https://www.luogu.com.cn/problem/P4559
解题思路:完全来自 小粉兔 大佬的博客
示例程序:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 5e5 + 5, maxm = 3e7, INF = 1.5e6 + 5;
#define ls(u) tr[u].l
#define rs(u) tr[u].r
struct Node {
int l, r, cnt;
ll sum;
} tr[maxm];
void push_up(int u) {
tr[u].cnt = tr[ls(u)].cnt + tr[rs(u)].cnt;
tr[u].sum = tr[ls(u)].sum + tr[rs(u)].sum;
}
int rt[maxn], idx;
void build(int val, int l, int r, int p, int &u) {
if (!u) u = ++idx;
if (l == r) {
tr[u].cnt++;
tr[u].sum += val;
return;
}
int mid = (l + r) >> 1;
if (val <= mid) {
build(val, l, mid, ls(p), ls(u));
rs(u) = rs(p);
}
else {
ls(u) = ls(p);
build(val, mid+1, r, rs(p), rs(u));
}
push_up(u);
}
int n, m, a[maxn];
ll query(int L, int R, int l, int r, int u1, int u2) {
if (!u2) return 0;
int cnt = tr[u2].cnt - tr[u1].cnt;
ll sum = tr[u2].sum - tr[u1].sum;
if (r <= L) { // 全都往右跑
return 1ll * (L + L + cnt-1) * cnt / 2 - sum;
}
if (l >= R) { // 全都往左跑
return sum - 1ll * (L + L + cnt-1) * cnt / 2;
}
int cnt_l = tr[ls(u2)].cnt - tr[ls(u1)].cnt, mid = (l + r) >> 1;
return query(L, L+cnt_l-1, l, mid, ls(u1), ls(u2)) + query(L+cnt_l, R, mid+1, r, rs(u1), rs(u2));
}
ll cal(int L, int R, int K) {
return query(K, K+R-L, 0, INF, rt[L-1], rt[R]);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", a+i);
build(a[i], 0, INF, rt[i-1], rt[i]);
}
for (int i = 0, l, r, K; i < m; i++) {
scanf("%d%d%d", &l, &r, &K);
ll ans = cal(l, r, K);
printf("%lld\n", ans);
}
return 0;
}
浙公网安备 33010602011771号