CF1638E Colorful Operations

发布时间 2024-01-03 08:41:07作者: cxqghzj

题意

给定一个长度为 \(n\) 的数组,初始每个数的颜色为 \(1\),值为 \(0\)

维护以下操作:

  • \(l \to r\) 的颜色替换成 \(c\)
  • 将数组中颜色为 \(c\) 的元素的值加上 \(x\)
  • 输出 \(a_i\) 的值。

\(n, q \le 10 ^ 6\)

Sol

通过操作1不难想到珂朵莉。

不难发现,只有区间推平的珂朵莉树的时间复杂度显然为 \(q \log n\)

考虑如何维护操作2,发现我们对于每个颜色开一个 \(tag\) 就行了。

考虑操作2对于操作1的影响,不难发现我们需要将区间内颜色段自身的 \(tag\) 先下放,然后再减掉新的颜色的 \(tag\)

区间修改单点查询,树状数组简单维护即可。

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <set>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE

/* #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++) */
/* char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf; */

#endif
int read() {
	int p = 0, flg = 1;
	char c = getchar();
	while (c < '0' || c > '9') {
		if (c == '-') flg = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		p = p * 10 + c - '0';
		c = getchar();
	}
	return p * flg;
}
void write(int x) {
	if (x < 0) {
		x = -x;
		putchar('-');
	}
	if (x > 9) {
		write(x / 10);
	}
	putchar(x % 10 + '0');
}
#define fi first
#define se second

const int N = 1e6 + 5;

namespace Bit {

array <int, N> edge;

int lowbit(int x) { return x & -x; }

void modify(int x, int y, int n) {
	while (x <= n) {
		edge[x] += y;
		x += lowbit(x);
	}
	return;
}

int query(int x) {
	int ans = 0;
	while (x) {
		ans += edge[x];
		x -= lowbit(x);
	}
	return ans;
}

}

namespace Chtholly {

class Node {

public:

	int l, r;
	mutable int v;

	Node (int _l, int _r, int _v) : l(_l), r(_r), v(_v) {}

	bool operator <(const Node &t) const { return l < t.l; }

};

array <int, N> tag;
set <Node> Cht;

auto split(int x, int n) {
	if (x > n) return Cht.end();
	auto it = --Cht.upper_bound(Node(x, 0, 0));
	int l = it -> l, r = it -> r, v = it -> v;
	if (l == x) return it;
	Cht.erase(it), Cht.insert(Node(l, x - 1, v));
	return Cht.insert(Node(x, r, v)).fi;
}

void assign(int l, int r, int n, int k) {
	auto itr = split(r + 1, n), itl = split(l, n);
	for (auto it = itl; it != itr; it++) {
		Bit::modify(it -> l, tag[it -> v], n);
		Bit::modify(it -> r + 1, -tag[it -> v], n);
	}
	Cht.erase(itl, itr), Cht.insert(Node(l, r, k));
	Bit::modify(l, -tag[k], n);
	Bit::modify(r + 1, tag[k], n);
}

int query(int x) {
	auto it = --Cht.upper_bound(Node(x, 0, 0));
	return tag[it -> v];
}

}

char strbuf[15];

signed main() {
	int n = read(), q = read();
	Chtholly::Cht.insert(Chtholly::Node(1, n, 1));
	while (q--) {
		scanf("%s", strbuf);
		if (strbuf[0] == 'C') {
			int l = read(), r = read(), k = read();
			Chtholly::assign(l, r, n, k);
		}
		if (strbuf[0] == 'A') {
			int x = read(), y = read();
			Chtholly::tag[x] += y;
		}
		if (strbuf[0] == 'Q') {
			int x = read();
			write(Bit::query(x) + Chtholly::query(x)), puts("");
		}
	}

	return 0;
}