답안 #1106101

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1106101 2024-10-29T08:47:37 Z Thunnus 가로등 (APIO19_street_lamps) C++17
100 / 100
1188 ms 113484 KB
/*
- Maintain a set of maximal segments of contiguous ones.
- Whenever a segment is removed, create a point (a, b, -t).
- Whenever a segment is added, create a point (a, b, +t).
- Now for each query (aq, bq, tq), count the number of points (a, b, t)
  such that a < aq , b > bq , t < tq (we don't take credit of equal elements because the given input is one-based)
- Find the total sum of t, and the number of negative and positive events.
- If one positive event is missing, add 't' into the total sum.
- This can be easily solved with CDQ divide and conquer.
- My previous idea was using a 2D sparse segment tree to do the same,
  but it uses too much memory. Alas, the remnants of my code were still there,
  so i decided to reuse the 1D version instead of creating a new code for a
  regular segment tree. 
*/
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
#define int i64
#define vi vector<int>
#define vvi vector<vi>
#define vb vector<bool>
#define pii pair<int, int>
#define fi first
#define se second
#define sz(x) (int)(x).size()

const int MX = 3e5 + 5;

pii operator +(const pii &a, const pii &b){
    return {a.fi + b.fi, a.se + b.se};
}

pii operator -(const pii &a, const pii &b){
    return {a.fi - b.fi, a.se - b.se};
}

struct BIT{
    vector<pii> bit;
    BIT(int n) : bit(n + 10) {}

    inline void add(int idx, pii val){
		if(idx < 0) return;
        for(++idx; idx < sz(bit); idx += idx & -idx){
            bit[idx] = bit[idx] + val;
        }
        return;
    }

    inline pii query(int idx){
		if(idx < 0) return {0, 0};
        pii ret = {0, 0};
        for(++idx; idx; idx -= idx & -idx){
            ret = ret + bit[idx];
        }
        return ret;
    }

    inline pii query(int l, int r){
        return query(r) - query(l - 1);
    }
};

vector<array<int, 5>> updates;
vector<pii> onans, offans;
BIT on(MX), off(MX);

inline void cdq(int l, int r){
    if(l + 1 == r) return;
    int m = (l + r) / 2;
    cdq(l, m); cdq(m, r);

    vector<pair<int, pii>> offrec, onrec;
    vector<array<int, 5>> temp;
    int a = l, b = m;
    while(a < m || b < r){
        bool left;
        int cur;
        if(a >= m || (b < r && updates[b][1] <= updates[a][1])) cur = b++, left = false;
        else cur = a++, left = true;
        temp.emplace_back(updates[cur]);

        if(left && updates[cur][3] == -1){
            off.add(updates[cur][2], {updates[cur][0], 1});
            offrec.push_back({updates[cur][2], {-updates[cur][0], -1}});
        }
        else if(left && updates[cur][3] == 1){
            on.add(updates[cur][2], {updates[cur][0], 1});
            onrec.push_back({updates[cur][2], {-updates[cur][0], -1}});
        }
        else if(!left && !updates[cur][3]){
            pii onval = on.query(updates[cur][2] + 1, MX - 1), offval = off.query(updates[cur][2] + 1, MX - 1);
            onans[updates[cur][4]] = onans[updates[cur][4]] + onval, offans[updates[cur][4]] = offans[updates[cur][4]] + offval;
        }
    }

    for(int i = 0; i < sz(offrec); i++){
        off.add(offrec[i].fi, offrec[i].se);
    }
    for(int i = 0; i < sz(onrec); i++){
        on.add(onrec[i].fi, onrec[i].se);
    }
    for(int i = l; i < r; i++){
        updates[i] = temp[i - l];
    }
    temp.clear(), offrec.clear(), onrec.clear();
    return;
}

signed main(){
    ios_base::sync_with_stdio(false); cin.tie(0);
    int n, q;
    string s, type;
    cin >> n >> q >> s;
    set<pii> seg;
    for(int i = 0; i < n; i++){
        if(s[i] == '1'){
            int l = i;
            while(i + 1 < n && s[i + 1] == '1') i++;
            seg.emplace(l, i);
            updates.push_back({0, l, i, 1});
        }
    }

    int qc = 0;
    vi qtime;
    for(int t = 1; t <= q; t++){
        cin >> type;
        if(type == "toggle"){
            int i;
            cin >> i;
            if(s[--i] == '0'){
                int l = i, r = i;
                auto right = seg.lower_bound({i, i});
                if(right != seg.end() && right->fi == i + 1){
                    r = right->se;
                    updates.push_back({t, i + 1, r, -1});
                    seg.erase(right);
                }

                auto left = seg.lower_bound({i, i});
                if(left != seg.begin()) left--;
                if(left != seg.end() && left->se == i - 1){
                    l = left->fi;
                    updates.push_back({t, l, i - 1, -1});
                    seg.erase(left);
                }
                seg.emplace(l, r);
                updates.push_back({t, l, r, 1});
                s[i] = '1';
            }
            else{
                auto it = prev(seg.lower_bound({i + 1, i + 1}));
                int l = it->fi, r = it->se;
                seg.erase(it);
                updates.push_back({t, l, r, -1});
                if(l < i){
                    updates.push_back({t, l, i - 1, 1});
                    seg.emplace(l, i - 1);
                }
                if(r > i){
                    updates.push_back({t, i + 1, r, 1});
                    seg.emplace(i + 1, r);
                }
                s[i] = '0';
            }
        }
        else{
            int ql, qr;
            cin >> ql >> qr;
            updates.push_back({t, ql, qr - 3, 0, qc++}); // qr - 3 ?
            qtime.emplace_back(t);
        }
    }
    sort(updates.begin(), updates.end());
    onans.resize(qc), offans.resize(qc);

    cdq(0, sz(updates));
    for(int i = 0; i < qc; i++){
        int ans = offans[i].fi - onans[i].fi;
        if(onans[i].se > offans[i].se) ans += qtime[i];
        cout << ans << "\n";
    }
    return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 2 ms 9808 KB Output is correct
2 Correct 2 ms 9656 KB Output is correct
3 Correct 2 ms 9808 KB Output is correct
4 Correct 3 ms 9808 KB Output is correct
5 Correct 3 ms 9860 KB Output is correct
6 Correct 2 ms 9808 KB Output is correct
7 Correct 2 ms 9808 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 655 ms 73904 KB Output is correct
2 Correct 681 ms 73908 KB Output is correct
3 Correct 642 ms 78016 KB Output is correct
4 Correct 850 ms 112656 KB Output is correct
5 Correct 818 ms 112624 KB Output is correct
6 Correct 818 ms 110932 KB Output is correct
7 Correct 439 ms 75512 KB Output is correct
8 Correct 422 ms 75252 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 6 ms 10064 KB Output is correct
2 Correct 4 ms 10064 KB Output is correct
3 Correct 4 ms 10064 KB Output is correct
4 Correct 3 ms 9808 KB Output is correct
5 Correct 802 ms 102548 KB Output is correct
6 Correct 812 ms 110832 KB Output is correct
7 Correct 755 ms 107284 KB Output is correct
8 Correct 423 ms 68348 KB Output is correct
9 Correct 177 ms 50900 KB Output is correct
10 Correct 246 ms 67008 KB Output is correct
11 Correct 245 ms 68272 KB Output is correct
12 Correct 421 ms 68856 KB Output is correct
13 Correct 443 ms 68400 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 10064 KB Output is correct
2 Correct 4 ms 10064 KB Output is correct
3 Correct 5 ms 9908 KB Output is correct
4 Correct 7 ms 10064 KB Output is correct
5 Correct 551 ms 88308 KB Output is correct
6 Correct 659 ms 86560 KB Output is correct
7 Correct 822 ms 111080 KB Output is correct
8 Correct 990 ms 113484 KB Output is correct
9 Correct 820 ms 78088 KB Output is correct
10 Correct 1107 ms 103632 KB Output is correct
11 Correct 809 ms 78196 KB Output is correct
12 Correct 1120 ms 103292 KB Output is correct
13 Correct 851 ms 78256 KB Output is correct
14 Correct 1188 ms 103136 KB Output is correct
15 Correct 451 ms 74456 KB Output is correct
16 Correct 471 ms 75056 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 2 ms 9808 KB Output is correct
2 Correct 2 ms 9656 KB Output is correct
3 Correct 2 ms 9808 KB Output is correct
4 Correct 3 ms 9808 KB Output is correct
5 Correct 3 ms 9860 KB Output is correct
6 Correct 2 ms 9808 KB Output is correct
7 Correct 2 ms 9808 KB Output is correct
8 Correct 655 ms 73904 KB Output is correct
9 Correct 681 ms 73908 KB Output is correct
10 Correct 642 ms 78016 KB Output is correct
11 Correct 850 ms 112656 KB Output is correct
12 Correct 818 ms 112624 KB Output is correct
13 Correct 818 ms 110932 KB Output is correct
14 Correct 439 ms 75512 KB Output is correct
15 Correct 422 ms 75252 KB Output is correct
16 Correct 6 ms 10064 KB Output is correct
17 Correct 4 ms 10064 KB Output is correct
18 Correct 4 ms 10064 KB Output is correct
19 Correct 3 ms 9808 KB Output is correct
20 Correct 802 ms 102548 KB Output is correct
21 Correct 812 ms 110832 KB Output is correct
22 Correct 755 ms 107284 KB Output is correct
23 Correct 423 ms 68348 KB Output is correct
24 Correct 177 ms 50900 KB Output is correct
25 Correct 246 ms 67008 KB Output is correct
26 Correct 245 ms 68272 KB Output is correct
27 Correct 421 ms 68856 KB Output is correct
28 Correct 443 ms 68400 KB Output is correct
29 Correct 4 ms 10064 KB Output is correct
30 Correct 4 ms 10064 KB Output is correct
31 Correct 5 ms 9908 KB Output is correct
32 Correct 7 ms 10064 KB Output is correct
33 Correct 551 ms 88308 KB Output is correct
34 Correct 659 ms 86560 KB Output is correct
35 Correct 822 ms 111080 KB Output is correct
36 Correct 990 ms 113484 KB Output is correct
37 Correct 820 ms 78088 KB Output is correct
38 Correct 1107 ms 103632 KB Output is correct
39 Correct 809 ms 78196 KB Output is correct
40 Correct 1120 ms 103292 KB Output is correct
41 Correct 851 ms 78256 KB Output is correct
42 Correct 1188 ms 103136 KB Output is correct
43 Correct 451 ms 74456 KB Output is correct
44 Correct 471 ms 75056 KB Output is correct
45 Correct 412 ms 60996 KB Output is correct
46 Correct 481 ms 61256 KB Output is correct
47 Correct 464 ms 67952 KB Output is correct
48 Correct 817 ms 112620 KB Output is correct
49 Correct 252 ms 72128 KB Output is correct
50 Correct 254 ms 72128 KB Output is correct
51 Correct 267 ms 71872 KB Output is correct
52 Correct 273 ms 73664 KB Output is correct
53 Correct 266 ms 72764 KB Output is correct
54 Correct 268 ms 72384 KB Output is correct