Submission #1276556

#TimeUsernameProblemLanguageResultExecution timeMemory
1276556bbldrizzy가로등 (APIO19_street_lamps)C++20
0 / 100
5094 ms4408 KiB
#include <bits/stdc++.h>
#include <ios>
#include <iostream>
#include <limits>
#include <random>
using namespace std;
using ll = long long;
using P = pair<int, int>;
#define f first
#define s second
const int MOD = 1e9+7;
const ll inf = 4*1e18;
const int mx = 5*1e5+5;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

template<typename T> struct SegTreeMax {
    int n;
    vector<T> st;
    vector<T> lazy;
    vector<char> has_lazy;
    T ID;       // identity for query (very small)
    T init_val; // value used to initialize all elements

    // default init_val is numeric max so you can do SegTreeMax<ll> st(n);
    SegTreeMax(int _n = 0, T _init_val = numeric_limits<T>::max()) {
        init(_n, _init_val);
    }

    // initialize or re-initialize with chosen init_val
    void init(int _n, T _init_val = numeric_limits<T>::max()) {
        n = _n;
        init_val = _init_val;
        ID = numeric_limits<T>::lowest();
        if (n <= 0) {
            st.clear(); lazy.clear(); has_lazy.clear();
            return;
        }
        st.assign(4 * n, init_val); // <- fill tree with your desired "max" value
        lazy.assign(4 * n, T());
        has_lazy.assign(4 * n, 0);
    }

    // build from 0-indexed array a (overrides init_val length if sizes differ)
    void build(const vector<T>& a) {
        if ((int)a.size() != n) init((int)a.size(), init_val);
        build(1, 0, n - 1, a);
    }

    // set range [l, r] to val
    void range_set(int l, int r, T val) {
        if (n == 0 || l > r) return;
        range_set(1, 0, n - 1, l, r, val);
    }

    // query max on [l, r]
    T query(int l, int r) {
        if (n == 0 || l > r) return ID;
        return query(1, 0, n - 1, l, r);
    }

private:
    void apply_set(int v, int tl, int tr, T val) {
        st[v] = val;
        lazy[v] = val;
        has_lazy[v] = 1;
    }

    void push(int v, int tl, int tr) {
        if (!has_lazy[v] || tl == tr) return;
        int tm = (tl + tr) >> 1;
        apply_set(v<<1, tl, tm, lazy[v]);
        apply_set(v<<1|1, tm+1, tr, lazy[v]);
        has_lazy[v] = 0;
    }

    void build(int v, int tl, int tr, const vector<T>& a) {
        has_lazy[v] = 0;
        if (tl == tr) {
            st[v] = a[tl];
            return;
        }
        int tm = (tl + tr) >> 1;
        build(v<<1, tl, tm, a);
        build(v<<1|1, tm+1, tr, a);
        st[v] = max(st[v<<1], st[v<<1|1]);
    }

    void range_set(int v, int tl, int tr, int l, int r, T val) {
        if (l > r) return;
        if (l == tl && r == tr) {
            apply_set(v, tl, tr, val);
            return;
        }
        push(v, tl, tr);
        int tm = (tl + tr) >> 1;
        if (r <= tm) range_set(v<<1, tl, tm, l, r, val);
        else if (l > tm) range_set(v<<1|1, tm+1, tr, l, r, val);
        else {
            range_set(v<<1, tl, tm, l, tm, val);
            range_set(v<<1|1, tm+1, tr, tm+1, r, val);
        }
        st[v] = max(st[v<<1], st[v<<1|1]);
    }

    T query(int v, int tl, int tr, int l, int r) {
        if (l > r) return ID;
        if (l == tl && r == tr) return st[v];
        push(v, tl, tr);
        int tm = (tl + tr) >> 1;
        return max(
            query(v<<1, tl, tm, l, min(r, tm)),
            query(v<<1|1, tm+1, tr, max(l, tm+1), r)
        );
    }
};

template <class T> class BIT {
  private:
	int size;
	vector<T> bit;
	vector<T> arr;

  public:
	BIT(int size) : size(size), bit(size + 1), arr(size) {}

	/** Sets the value at index ind to val. */
	void set(int ind, T val) { add(ind, val - arr[ind]); }

	/** Adds val to the element at index ind. */
	void add(int ind, T val) {
		arr[ind] += val;
		ind++;
		for (; ind <= size; ind += ind & -ind) { bit[ind] += val; }
	}

	/** @return The sum of all values in [0, ind]. */
	T pref_sum(int ind) {
		ind++;
		T total = 0;
		for (; ind > 0; ind -= ind & -ind) { total += bit[ind]; }
		return total;
	}
};

int main() {
    int n, q; cin >> n >> q;
    string s1; cin >> s1;
    BIT<ll> ft1(n);
    BIT<ll> ft2(n);
    SegTreeMax<ll> seg(n);
    set<pair<ll, ll>> st;
    int str = -1;
    int en = -1;
    for (int i = 0; i < n; i++) {
        if (s1[i] - '0' == 0) {
            if (str != -1) {
                st.insert({str, en});
            }
            str = -1; 
        } else {
            seg.range_set(i, i, 0);
            if (str == -1) str = i;
            en = i;
            if (i == n-1) {
                st.insert({str, en});
            }
        }
    }
    // cout << seg.query(0, 1);
    // cout << "\n";
    // for (auto it: st) {
    //     cout << it.f << ", " << it.s << '\n';
    // }
    for (int i = 1; i <= q; i++) {
        string S; cin >> S;
        if (S == "query") {
            int a, b; cin >> a >> b; --a; b -= 2;
            ll x = seg.query(a, b);
            ll ans = 0;
            if (x != numeric_limits<ll>::max()) {
                ans += i-x;
            }
            ans += ft1.pref_sum(a);
            ans += ft2.pref_sum(n-1-b);
            ans -= ft1.pref_sum(n-1);
            cout << ans << "\n";
        } else {
            int x; cin >> x; --x;
            if (s1[x] == '0') {
                seg.range_set(x, x, i);
                int l = x; int r = x;
                auto it1 = st.upper_bound({x, 0});
                auto it2 = it1;
                bool one = false; bool two = false;
                if (it1 != st.end() && (*it1).f == x+1) {
                    one = true;
                    r = (*it1).s;
                    int vl = seg.query((*it1).f, (*it2).s);
                    ft1.add((*it1).f, i-vl);
                    ft2.add(n-1-(*it1).s, i-vl);
                    seg.range_set((*it1).f, (*it2).s, i);
                }
                if (it2 != st.begin()) {
                    it2--;
                    if ((*it2).s == x-1) {
                        l = (*it2).f;
                        two = true;
                        int vl = seg.query((*it2).f, (*it2).s);
                        ft1.add((*it2).f, i-vl);
                        ft2.add(n-1-(*it2).s, i-vl);
                        seg.range_set((*it2).f, (*it2).s, i);
                    }
                }
                if (one) st.erase(it1);
                if (two) st.erase(it2);
                st.insert({l, r});
            } else {
                auto it1 = st.upper_bound({x, 0});
                if (it1 != st.begin()) {
                    it1--;
                    int l1 = 1; int r1 = 0; int l2 = 1; int r2 = 0;
                    if (x >= (*it1).f && x <= (*it1).s) {
                        l1 = (*it1).f; r1 = x-1;
                        l2 = x+1; r2 = (*it1).s;
                        st.erase(it1);
                        ll v = seg.query(l1, r2);
                        ft1.add(l1, i-v);
                        ft2.add(n-1-l2, i-v);
                        if (l1 <= r1) {
                            st.insert({l1, r1});
                            seg.range_set(l1, r1, i);
                        }
                        if (l2 <= r2) {
                            st.insert({l2, r2});
                            seg.range_set(l2, r2, i);
                        }
                    } else {
                        st.erase(it1);
                        l1 = x; l2 = x;
                        ll v = seg.query(l1, r2);
                        ft1.add(l1, i-v);
                        ft2.add(n-1-l2, i-v);
                    }
                    seg.range_set(x, x, numeric_limits<ll>::max());
                }
            }
        }
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...