P12194 [NOISG 2025 Prelim] Snacks
题意
给定一个数组
- 将值在 \([l, r]\) 的元素都变成 \(x\)
- 求和
思路
由于是要操作值域上的区间,所以可以在值域上考虑这个问题。设 \(cnt_v\) 为 \(v\) 的出现次数,则 \(ans\) 为每一个 \(cnt_v \times v\) 的求和(\(ans\) 也就是最终答案),\(sum\) 为每一个 \(cnt_v\) 的求和。于是有初步思路,我们考虑一棵值域线段树,对于每一个区间维护这个 \(ans\) (具有可合并性)即可。进一步地,在值域上,我们可以将原来的操作转化为区间赋 0,单点加,区间查 \(ans\),区间查 \(sum\)。后两个简单,前两个操作手推维护 \(ans\)。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using ll = long long;
const int N = 2e5 + 5, INF = 1e9;
struct Node {
int ls, rs;
ll sum, res;
};
int n, m, tot, rt;
ll tg[N << 7];
Node t[N << 7], E = {0, 0, 0, 0};
Node F(Node a, ll b, ll l, ll r) {
a.sum = (r - l + 1) * b;
a.res = (l + r) * (r - l + 1) / 2 * b;
return a;
}
Node Up(Node b, Node c) {
Node a = E;
a.sum = c.sum + b.sum;
a.res = c.res + b.res;
return a;
}
void Add(int &u) {
if (!u) {
u = ++tot;
tg[u] = -1;
}
return ;
}
void Down(int u, int l, int r) {
if (tg[u] != -1) {
int mid = l + r >> 1;
Add(t[u].ls);
t[t[u].ls] = F(t[t[u].ls], tg[u], l, mid);
tg[t[u].ls] = tg[u];
Add(t[u].rs);
t[t[u].rs] = F(t[t[u].rs], tg[u], mid + 1, r);
tg[t[u].rs] = tg[u];
tg[u] = -1;
}
return ;
}
void Update1(int &u, int l, int r, int ul, int ur, ll v) {
Add(u);
if (ul <= l && r <= ur) {
t[u] = F(t[u], v, l, r);
tg[u] = v;
// cout << "U1 " << u << ' ' << l << ' ' << r << ' ' << t[u].sum << ' ' << t[u].res << ' ' << tg[u] << '\n';
return ;
}
if (ur < l || r < ul) {
return ;
}
Down(u, l, r);
int mid = l + r >> 1;
Update1(t[u].ls, l, mid, ul, ur, v);
Update1(t[u].rs, mid + 1, r, ul, ur, v);
t[u].sum = t[t[u].ls].sum + t[t[u].rs].sum;
t[u].res = t[t[u].ls].res + t[t[u].rs].res;
return ;
}
void Update2(int &u, int l, int r, int x, ll v) {
Add(u);
if (x < l || r < x) {
return ;
}
if (l == r) {
t[u].sum += v;
t[u].res += v * l;
// cout << "U2 " << u << ' ' << l << ' ' << r << ' ' << t[u].sum << ' ' << t[u].res << '\n';
return ;
}
Down(u, l, r);
int mid = l + r >> 1;
Update2(t[u].ls, l, mid, x, v);
Update2(t[u].rs, mid + 1, r, x, v);
t[u].sum = t[t[u].ls].sum + t[t[u].rs].sum;
t[u].res = t[t[u].ls].res + t[t[u].rs].res;
return ;
}
Node Query(int u, int l, int r, int ql, int qr) {
if (!u) {
return E;
}
if (ql <= l && r <= qr) {
// cout << "Q " << u << ' ' << l << ' ' << r << ' ' << t[u].sum << ' ' << t[u].res << '\n';
return t[u];
}
if (qr < l || r < ql) {
return E;
}
Down(u, l, r);
int mid = l + r >> 1;
return Up(Query(t[u].ls, l, mid, ql, qr), Query(t[u].rs, mid + 1, r, ql, qr));
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1, x; i <= n; i++) {
cin >> x;
Update2(rt, 0, INF, x, 1);
}
cout << t[rt].res << '\n';
for (int i = 1, l, r, x; i <= m; i++) {
cin >> l >> r >> x;
int sum = Query(rt, 0, INF, l, r).sum;
Update1(rt, 0, INF, l, r, 0);
Update2(rt, 0, INF, x, sum);
cout << t[rt].res << '\n';
}
return 0;
}

浙公网安备 33010602011771号