답안 #545478

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
545478 2022-04-04T14:59:52 Z tranxuanbach Raspad (COI17_raspad) C++17
0 / 100
548 ms 1048576 KB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
 
#define endl '\n'
#define fi first
#define se second
#define For(i, l, r) for (auto i = l; i < r; i++)
#define ForE(i, l, r) for (auto i = l; i <= r; i++)
#define FordE(i, l, r) for (auto i = l; i >= r; i--)
#define Fora(v, a) for (auto v: a)
#define bend(a) a.begin(), a.end()
#define isz(a) ((signed)a.size())
 
using ll = long long;
using ld = long double;
using pii = pair <int, int>;
using vi = vector <int>;
using vpii = vector <pair <int, int>>;
using vvi = vector <vector <int>>;
 
const int N = 1e5 + 5, M = 50 + 2;
 
struct disjoint_set_union{
    int par[2 * M], val[2 * M];
 
    void reset(int len){
        fill(par + 1, par + len + 1, -1);
        fill(val + 1, val + len + 1, 0);
    }
 
    int root(int x){
        return par[x] < 0 ? x : (par[x] = root(par[x]));
    }
 
    pii ansmerge;
 
    bool merge(int x, int y){
        if ((x = root(x)) == (y = root(y))){
            return 0;
        }
        if (par[x] > par[y]){
            swap(x, y);
        }
        par[x] += par[y];
        par[y] = x;
        ansmerge = make_pair(val[x], val[y]);
        if (val[x] == 0){
            val[x] = val[y];
        }
        else if (val[y] == 0){
 
        }
        else{
            val[x] = min(val[x], val[y]);
        }
        return 1;
    }
} dsu[3];
 
int n, m;
char a[N][M];
 
ll ans;

int root[N * M];
int pos[2 * M];
 
void find_interval(const vector <pair <int, pii>> &a, vector <pair <int, pii>> &b){
    b.clear();
    int l = 0;
    ForE(r, 1, isz(a)){
        if (r == isz(a) or a[r].fi != a[r - 1].fi){
            b.emplace_back(a[l].fi, make_pair(l, r - 1));
            l = r;
        }
    }
}
 
void divide_and_conquer(int l, int r){
    if (l == r){
        ForE(j, 1, m){
            if (a[l][j - 1] == '0' and a[l][j] == '1'){
                ans++;
            }
        }
        return;
    }
 
    int mid = (l + r) >> 1;
    divide_and_conquer(l, mid);
    divide_and_conquer(mid + 1, r);
 
    vector <pair <int, pii>> mergel = {{mid, {0, 0}}}, merger = {{mid + 1, {0, 0}}};
    {
        int ctridx = 0;
        dsu[mid & 1].reset(2 * m);
        ForE(j, 1, m){
            if (a[mid][j] != '1'){
                continue;
            }
            dsu[mid & 1].val[j] = ++ctridx;
            if (a[mid][j - 1] == '1'){
                dsu[mid & 1].merge(j - 1, j);
            }
        }
 
        int idx_colmid = ctridx;
        int cnt = 0;
 
        FordE(i, mid - 1, l){
            int ii = i & 1;
            dsu[ii].reset(2 * m);
            ForE(j, 1, m){
                root[dsu[ii ^ 1].val[dsu[ii ^ 1].root(j)]] = j + m;
            }
            ForE(j, 1, m){
                dsu[ii].val[j + m] = dsu[ii ^ 1].val[dsu[ii ^ 1].root(j)];
                dsu[ii].merge(j + m, root[dsu[ii ^ 1].val[dsu[ii ^ 1].root(j)]]);
            }
            ForE(j, 1, m){
                if (a[i][j] != '1'){
                    continue;
                }
                if (a[i + 1][j] == '1'){
                    dsu[ii].merge(j, j + m);
                }
                else{
                    dsu[ii].val[j] = ++ctridx;
                    cnt++;
                }
                if (a[i][j - 1] == '1'){
                    if (dsu[ii].merge(j - 1, j)){
                        if (dsu[ii].ansmerge.fi > idx_colmid or dsu[ii].ansmerge.se > idx_colmid){
                            cnt--;
                        }
                        else{
                            mergel.emplace_back(i, dsu[ii].ansmerge);
                        }
                    }
                }
            }
            ans += (ll)cnt * (r - mid);
        }
    }
    // cout << "STEP 1 " << l << ' ' << r << ' ' << ans << endl;
    {
        int ctridx = 0;
        dsu[(mid + 1) & 1].reset(2 * m);
        ForE(j, 1, m){
            if (a[mid + 1][j] != '1'){
                continue;
            }
            dsu[(mid + 1) & 1].val[j] = ++ctridx;
            if (a[mid + 1][j - 1] == '1'){
                dsu[(mid + 1) & 1].merge(j - 1, j);
            }
        }
 
        int idx_colmid = ctridx;
        int cnt = 0;
 
        ForE(i, mid + 2, r){
            int ii = i & 1;
            dsu[ii].reset(2 * m);
            ForE(j, 1, m){
                root[dsu[ii ^ 1].val[dsu[ii ^ 1].root(j)]] = j + m;
            }
            ForE(j, 1, m){
                dsu[ii].val[j + m] = dsu[ii ^ 1].val[dsu[ii ^ 1].root(j)];
                dsu[ii].merge(j + m, root[dsu[ii ^ 1].val[dsu[ii ^ 1].root(j)]]);
            }
            ForE(j, 1, m){
                if (a[i][j] != '1'){
                    continue;
                }
                if (a[i - 1][j] == '1'){
                    dsu[ii].merge(j, j + m);
                }
                else{
                    dsu[ii].val[j] = ++ctridx;
                    cnt++;
                }
                if (a[i][j - 1] == '1'){
                    if (dsu[ii].merge(j - 1, j)){
                        if (dsu[ii].ansmerge.fi > idx_colmid or dsu[ii].ansmerge.se > idx_colmid){
                            cnt--;
                        }
                        else{
                            merger.emplace_back(i, dsu[ii].ansmerge);
                        }
                    }
                }
            }
            ans += (ll)cnt * (mid - l + 1);
        }
    }
    // cout << "STEP 2 " << l << ' ' << r << ' ' << ans << endl;
 
    // cout << "MERGEL" << endl;
    // Fora(elem, mergel){
    //     cout << elem.fi << ' ' << elem.se.fi << ' ' << elem.se.se << endl;
    // }
    // cout << "MERGER" << endl;
    // Fora(elem, merger){
    //     cout << elem.fi << ' ' << elem.se.fi << ' ' << elem.se.se << endl;
    // }
    vector <pair <int, pii>> itvmergel, itvmerger;
    find_interval(mergel, itvmergel);
    find_interval(merger, itvmerger);
 
    For(il, 0, isz(itvmergel)){
        int lenl = itvmergel[il].fi - (il == isz(itvmergel) - 1 ? l - 1 : itvmergel[il + 1].fi);
        dsu[2].reset(2 * m);
        int cnt = 0, itr = 0;
        ForE(j, 1, m){
            if (a[mid][j - 1] == '0' and a[mid][j] == '1'){
                itr++;
                cnt++;
                pos[j] = itr;
                dsu[2].val[itr] = itr;
            }
            else if (a[mid][j] == '1'){
                itr++;
                pos[j] = pos[j - 1];
            }
        }
 
        if (il != 0){
            ForE(til, 1, itvmergel[il].se.se){
                if (dsu[2].merge(mergel[til].se.fi, mergel[til].se.se)){
                    cnt--;
                }
            }
        }
 
        itr = m;
        ForE(j, 1, m){
            if (a[mid + 1][j - 1] == '0' and a[mid + 1][j] == '1'){
                itr++;
                cnt++;
                pos[j + m] = itr;
                dsu[2].val[itr] = itr;
            }
            else if (a[mid + 1][j] == '1'){
                itr++;
                pos[j + m] = pos[j + m - 1];
            }
            if (a[mid][j] == '1' and a[mid + 1][j] == '1'){
                if (dsu[2].merge(pos[j], pos[j + m])){
                    cnt--;
                }
            }
        }
        For(ir, 0, isz(itvmerger)){
            int lenr = (ir == isz(itvmerger) - 1 ? r + 1 : itvmerger[ir + 1].fi) - itvmerger[ir].fi;
            if (ir != 0){
                ForE(tir, itvmerger[ir].se.fi, itvmerger[ir].se.se){
                    if (dsu[2].merge(merger[tir].se.fi + m, merger[tir].se.se + m)){
                        cnt--;
                    }
                }
            }
            // cout << "ADD ANS " << il << ' ' << ir << ' ' << lenl << ' ' << lenr << ' ' << cnt << endl;
            ans += (ll)lenl * lenr * cnt;
        }
    }
    // cout << "STEP 3 " << l << ' ' << r << ' ' << ans << endl;
}
 
signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    freopen("KEK.inp", "r", stdin);
    freopen("KEK.out", "w", stdout);
    cin >> n >> m;
    ForE(i, 1, n){
        ForE(j, 1, m){
            cin >> a[i][j];
        }
    }
 
    ForE(i, 1, n){
        a[i][0] = a[i][m + 1] = '0';
    }
 
    divide_and_conquer(1, n);
    cout << ans << endl;
}
 
/*
==================================================+
INPUT:                                            |
--------------------------------------------------|
 
--------------------------------------------------|
==================================================+
OUTPUT:                                           |
--------------------------------------------------|
 
--------------------------------------------------|
==================================================+
*/

Compilation message

raspad.cpp: In function 'int main()':
raspad.cpp:276:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  276 |     freopen("KEK.inp", "r", stdin);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
raspad.cpp:277:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  277 |     freopen("KEK.out", "w", stdout);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Runtime error 548 ms 1048576 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 548 ms 1048576 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 479 ms 1048576 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 548 ms 1048576 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -