Codeforces Round #771 (Div. 2) E 题解

源自:Codeforces Round #771 (Div. 2) E Colorful Operations

题意:

你有一个长度为 n 的数组。对于所有在 [1,n] 内的整数 i,第 i 个元素 ai,一开始的值为 0,颜色为 1

你需要执行 q 次操作,每次操作为如下三种之一:

  1. Color l r c :将 al,al+1,,ar的颜色替换为 c
  2. Add c x:将数组中颜色为 c 的所有元素的值加上 x
  3. Query i :输出 ai 的值。

数据范围:

  • 1n,q106
  • 对于操作 1,1lrn1cn
  • 对于操作 2,1cn109x109
  • 对于操作 3,1in

分析

用常规的数据结构已经无法处理了,例如用线段树,操作1区间覆盖很简单,但是操作2无法在 O(logn) 时间内统计完成。
观察到操作1为区间染色,珂朵莉树能很好的处理这类问题。即使数据不随机,仅有操作1的话时间复杂度也能保证为
O(nlognlogn)

如何处理操作2成为本题的关键。

但发现,记录颜色为 c 的区间然后整段增减的操作是不可行的,因为珂朵莉树的操作只有染色时间复杂度是正确的 。
我们再将思路回到操作1:

  1. 列出 (l,r) 之间的所有段
  2. 删除这些段 每段的颜色 i
  3. 插入 [l,r]段,颜色为 j

在重新染色时,原有段的颜色会变为新颜色,而操作2也是针对于某种特定的颜色。
所以我们可以把对象从数组的元素变更为 颜色,对于每种颜色 设 vali记录整体变化,而当属于这个颜色的某一段由操作1变为另一种颜色时,只需要对这段的元素

anskansk+valivalj(i表示旧颜色j表示新颜色)

操作2只需变更 vali

操作3答案为 ansk+valck

代码

// from :
#include<bits/stdc++.h>
using namespace std;
#define fastio cin.tie(0);cout.tie(0);ios::sync_with_stdio(false)
typedef pair<int, int> PII;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
void debug(int x = 0) {
	cout << "--ok(" << x << ")" << endl;
}
void yes() {
	cout << "YES" << "\n";
}
void no() {
	cout << "NO" << "\n";
}
const int N = 1e6 + 5, M = 3e5 + 5, mod = 1e9 + 7;
/* cout << "\n";*/
struct P {
  int l, r;
  mutable int c;
  P(const int &il, const int &ir, const int &ic) : l(il), r(ir), c(ic){}

  inline bool operator<(const P &o) const { return l < o.l; }
};
set<P> s; 
int n, m; 
ll tag[N];
ll c[N];
void add(int x, ll y) {
	for (; x <= n; x += x & -x) c[x] += y;
}
ll ask(int x) {
	ll ans = 0;
	for (; x; x -= x & -x) ans += c[x];
	return ans;
}
auto split(int x) {
	if (x > n) return s.end();
	auto it = --s.upper_bound(P(x, 0, 0));
	if (it -> l == x) return it;
	int l = it -> l, r = it -> r;int c = it -> c;
	s.erase(it);
	s.insert(P(l, x - 1, c));
	return s.insert(P(x, r, c)).first;
}
void assign(int l, int r, int c) {
	auto itr = split(r + 1), itl = split(l);
	for (; itl != itr; ++itl) {
		add(itl -> l, tag[itl -> c]);
		add(itl -> r + 1, -tag[itl -> c]);
	}
	itl = split(l);
	s.erase(itl, itr);
	add(l, -tag[c]);
	add(r + 1, tag[c]);
	s.insert(P(l, r, c));
}

int getc(int x) {
	auto it = --s.upper_bound(P(x, 0, 0));
	return it -> c;
}

void solve() {
	cin >> n >> m;
	s.insert(P(1, n, 1));
	while (m--) {
		string op; int l, r, c;
		cin >> op >> l;
		if (op == "Color") {
			cin >> r >> c;
			assign(l, r, c);
		}
		else if (op == "Add") {
			cin >> r;
			tag[l] += r;
		}
		else {
			//cout << it -> c << "\n";
			cout << ask(l) + tag[getc(l)] << "\n";
		}
	}
}
int main(){
	fastio; cout << setprecision(10);
	solve();
	return 0;
}
posted @   九尾妖渚  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示