Codeforces Round #771 (Div. 2) E 题解
源自:Codeforces Round #771 (Div. 2) E Colorful Operations
题意:
你有一个长度为 的数组。对于所有在 内的整数 ,第 个元素 ,一开始的值为 ,颜色为 。
你需要执行 次操作,每次操作为如下三种之一:
- :将 的颜色替换为 。
- :将数组中颜色为 的所有元素的值加上 。
- :输出 的值。
数据范围:
- 。
- 对于操作 1,,
- 对于操作 2,, 。
- 对于操作 3, 。
分析
用常规的数据结构已经无法处理了,例如用线段树,操作1区间覆盖很简单,但是操作2无法在 时间内统计完成。
观察到操作1为区间染色,珂朵莉树能很好的处理这类问题。即使数据不随机,仅有操作1的话时间复杂度也能保证为
。
如何处理操作2成为本题的关键。
但发现,记录颜色为 的区间然后整段增减的操作是不可行的,因为珂朵莉树的操作只有染色时间复杂度是正确的 。
我们再将思路回到操作1:
- 列出 之间的所有段
- 删除这些段 每段的颜色
- 插入 段,颜色为
在重新染色时,原有段的颜色会变为新颜色,而操作2也是针对于某种特定的颜色。
所以我们可以把对象从数组的元素变更为 颜色,对于每种颜色 设 记录整体变化,而当属于这个颜色的某一段由操作1变为另一种颜色时,只需要对这段的元素
操作2只需变更
操作3答案为
代码
// 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?