トピックリンク:体育の授業
一般的なアイデア
nnの長さが与えられたn 's01 010 1シーケンス、2つの操作があります:間隔を置く[l、r] [l、r][ l 、r ]すべてが11になります1、または間隔を置く[l、r] [l、r][ l 、r ]すべてが00になります0。
各操作の後、出力シーケンスの111つの番号。
問題解決のアイデア
ことりの木
これはこどりツリーボードの質問ではありませんか?こどりツリーのインターバルレベリングを達成する必要があります。
クエリごとに、可変の合計を維持できることは言及する価値がありますそれを行う方法を合計するO(1)O(1)O (1 )クエリ。
それ以外の場合、毎回セット全体をトラバースすると、タイムアウトになります。
➡️線分ツリーの問題の解決策はここをクリック⬅️
ACコード
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
struct node {
int l, r; mutable ll v;
bool operator< (const node& t) const {
return l < t.l; }
}; set<node> st;
int sum;
auto split(int x) {
auto it = st.lower_bound({
x, 0, 0 });
if (it != st.end() and it->l == x) return it;
--it;
auto [l, r, v] = *it;
st.erase(it); st.insert({
l, x - 1, v });
return st.insert({
x, r, v }).first;
}
void assign(int l, int r, int c) {
auto R = split(r + 1), L = split(l);
for (auto it = L; it != R; ++it) {
if (it->v == 1) sum -= it->r - it->l + 1;
}
st.erase(L, R); st.insert({
l, r, c });
if (c) sum += r - l + 1;
}
int main()
{
int n, m; cin >> n >> m;
st.insert({
1, n, 1 });
sum = n;
rep(i, m) {
int l, r, tp; scanf("%d %d %d", &l, &r, &tp);
assign(l, r, tp - 1);
printf("%d\n", sum);
}
return 0;
}