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;
}  	
posted @ 2025-11-22 15:09  oymz  阅读(3)  评论(0)    收藏  举报