제출 #1023896

#제출 시각아이디문제언어결과실행 시간메모리
1023896Dzadzo자리 배치 (IOI18_seats)C++17
100 / 100
1576 ms188632 KiB
#include <bits/stdc++.h>
#include "seats.h"
#define ll long long
#define pb push_back
#define S second
#define F first
#define pii pair<int,int>
#define vi vector<int>
#define vvi vector<vi>
#define vvvi vector<vvi>
#define vp vector<pii>
#define vvp vector<vp>
#define vb vector<bool>
#define vvb vector<vb>
#define INF 2000000
#define MOD 1000000007
#define MAXN 1000000
using namespace std;
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
class SegmentTree {
private:
    struct Node {
        int minVal;
        int count;
        int lazy;

        Node(int minVal = numeric_limits<int>::max(), int count = 0, int lazy = 0)
            : minVal(minVal), count(count), lazy(lazy) {}
    };

    vector<Node> tree;
    int size;

    void apply(int pos, int delta) {
        tree[pos].minVal += delta;
        tree[pos].lazy += delta;
    }

    void push(int pos) {
        apply(2 * pos, tree[pos].lazy);
        apply(2 * pos + 1, tree[pos].lazy);
        tree[pos].lazy = 0;
    }

    void pull(int pos) {
        if (tree[2 * pos].minVal < tree[2 * pos + 1].minVal) {
            tree[pos].minVal = tree[2 * pos].minVal;
            tree[pos].count = tree[2 * pos].count;
        } else if (tree[2 * pos].minVal > tree[2 * pos + 1].minVal) {
            tree[pos].minVal = tree[2 * pos + 1].minVal;
            tree[pos].count = tree[2 * pos + 1].count;
        } else {
            tree[pos].minVal = tree[2 * pos].minVal;
            tree[pos].count = tree[2 * pos].count + tree[2 * pos + 1].count;
        }
    }

public:
    SegmentTree(const vector<int>& arr) {
        size = arr.size();
        tree.resize(2 * size);
        for (int i = 1; i <= size; ++i) {
            tree[size + i - 1] = Node(arr[i - 1], 1);
        }
        for (int i = size - 1; i > 0; --i) {
            pull(i);
        }
    }

    void rangeAdd(int l, int r, int delta) {
        if( l > r ) return;

        l += size - 1;
        r += size - 1;
        int l0 = l, r0 = r;

        while (l <= r) {
            if (l % 2 == 1) apply(l++, delta);
            if (r % 2 == 0) apply(r--, delta);
            l /= 2;
            r /= 2;
        }

        for (int i : {l0 / 2, r0 / 2}) {
            while (i > 0) {
                push(i);
                pull(i);
                i /= 2;
            }
        }
    }

    pair<int, int> query() {
        push(1); // Ensure root is up-to-date
        return {tree[1].minVal, tree[1].count};
    }
};



SegmentTree st(vi(MAXN));
vvi arr;
vvb seen;
int n, H, W;

void add(int x, int y, int t) {
    vi v = {arr[x][y], arr[x + 1][y], arr[x][y + 1], arr[x + 1][y + 1]};
    sort(v.begin(), v.end());
    st.rangeAdd( v[0], min(n, v[1] - 1), t);
    st.rangeAdd( v[2], min(n, v[3] - 1), t);
}

vi R, C;

void give_initial_chart(int h, int w, vi r, vi c) {
    R = r;
    C = c;
    H = h;
    W = w;
    n = H * W;
    st.rangeAdd(n+1, MAXN, INF);
    arr.resize(H + 2, vi(W + 2, 0));
    seen.resize(H + 2, vb(W + 2, false));
    for (int i = 0; i < n; i++) arr[R[i] + 1][C[i] + 1] = i + 1;
    for (int i = 0; i <= W + 1; i++) arr[0][i] = arr[H + 1][i] = INF;
    for (int i = 0; i <= H + 1; i++) arr[i][0] = arr[i][W + 1] = INF;

    for (int i = 0; i <= H; i++)
        for (int j = 0; j <= W; j++)
            add(i, j, 1);
}

int swap_seats(int a, int b) {
    vp cur = {
        {R[a] + 1, C[a] + 1}, {R[a], C[a] + 1}, {R[a] + 1, C[a]},
        {R[a], C[a]}, {R[b] + 1, C[b] + 1}, {R[b] + 1, C[b]},
        {R[b], C[b] + 1}, {R[b], C[b]}
    };

    for (auto &[x, y] : cur) {
        if (!seen[x][y]) add(x, y, -1);
        seen[x][y] = true;
    }

    for (auto &[x, y] : cur) seen[x][y] = false;

    swap(arr[R[a] + 1][C[a] + 1], arr[R[b] + 1][C[b] + 1]);
    swap(R[a], R[b]);
    swap(C[a], C[b]);

    for (auto &[x, y] : cur) {
        if (!seen[x][y]) add(x, y, 1);
        seen[x][y] = true;
    }

    for (auto &[x, y] : cur) seen[x][y] = false;

    return st.query().S;
}
// signed main(){
//     give_initial_chart(1,5,{0, 0, 0, 0, 0},{0, 1, 2, 3, 4});
//     cout<<swap_seats(0,1)<<'\n';
//     cout<<swap_seats(0,3)<<'\n';
//     cout<<swap_seats(4,0)<<'\n';
// }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...