Submission #267125

#TimeUsernameProblemLanguageResultExecution timeMemory
267125dooweyRectangles (IOI19_rect)C++14
72 / 100
5084 ms698548 KiB
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include "rect.h"

using namespace std;

typedef long long ll;
typedef pair<short, short> pii;

#define fi first
#define se second
#define mp make_pair

const int N = 2505;
short lef[N][N];
short rig[N][N];
short up[N][N];
short dow[N][N];

vector<pii> rr[N][N];
vector<pii> dd[N][N];


struct segtree{
    short n;
    int mode;
    vector<short> vals;
    void init(short sz, short md){
        n = sz;
        mode = md;
        vals.resize(n * 2);
    }
    void upd(short x, short v){
        if(mode == 0 && v == -1)
            v = 5005;
        x += n;
        vals[x] = v;
        x >>= 1;
        while(x > 0){
            if(mode == 0) vals[x] = min(vals[x * 2], vals[x * 2 + 1]);
            else vals[x] = max(vals[x * 2], vals[x * 2 + 1]);
            x >>= 1;
        }
    }
    short get(int l, int r){
        l += n;
        r += n;
        short sol = 5005;
        if(mode == 1) sol = -1;
        while(l <= r){
            if((l & 1)){
                if(mode == 0) sol = min(sol, vals[l]);
                else sol = max(sol, vals[l]);
                l ++ ;
            }
            if(!(r & 1)){
                if(mode == 0) sol = min(sol, vals[r]);
                else sol = max(sol, vals[r]);
                r -- ;
            }
            l >>= 1;
            r >>= 1;
        }
        return sol;
    }
};

segtree L[N], R[N], U[N], D[N];

bool is_valid(short i1, short j1, short i2, short j2){
    if(D[i1].get(j1 + 1 ,j2 - 1) < i2) return false;
    if(U[i2].get(j1 + 1, j2 - 1) > i1) return false;
    if(R[j1].get(i1 + 1, i2 - 1) < j2) return false;
    if(L[j2].get(i1 + 1, i2 - 1) > j1) return false;
    return true;
}

ll count_rectangles(vector<vector<int>>a) {
	short n = a.size();
	short m = a[0].size();
    for(int i = 0 ; i < n; i ++ ){
        vector<short> mn;
        for(int j = 0 ; j < m ; j ++ ){
            lef[i][j]=-1;
            while(!mn.empty() && a[i][mn.back()] < a[i][j]){
                mn.pop_back();
            }
            if(!mn.empty())
                lef[i][j] = mn.back();
            mn.push_back(j);
        }
        mn.clear();
        for(int j = m - 1; j >= 0 ; j -- ){
            rig[i][j]=-1;
            while(!mn.empty() && a[i][mn.back()] < a[i][j]){
                mn.pop_back();
            }
            if(!mn.empty())
                rig[i][j] = mn.back();
            mn.push_back(j);
        }
        for(int j = 0 ; j < m ; j ++ ){
            if(rig[i][j] != -1 && rig[i][j] > j + 1){
                rr[i][j].push_back(mp(i, rig[i][j]));
            }
            if(lef[i][j] != -1 && lef[i][j] + 1 < j){
                rr[i][lef[i][j]].push_back(mp(i,j));
            }
        }
    }
    for(int j = 0 ; j < m ; j ++ ){
        vector<short> mn;
        for(int i = 0 ; i < n; i ++ ){
            up[i][j]=-1;
            while(!mn.empty() && a[mn.back()][j] < a[i][j]){
                mn.pop_back();
            }
            if(!mn.empty())
                up[i][j] = mn.back();
            mn.push_back(i);
        }
        mn.clear();
        for(int i = n - 1; i >= 0 ; i -- ){
            dow[i][j]=-1;
            while(!mn.empty() && a[mn.back()][j] < a[i][j]){
                mn.pop_back();
            }
            if(!mn.empty())
                dow[i][j] = mn.back();
            mn.push_back(i);
        }
        for(int i = 0 ; i < n; i ++ ){
            if(dow[i][j] != -1 && i + 1 < dow[i][j]){
                dd[i][j].push_back(mp(dow[i][j], j));
            }
            if(up[i][j] != -1 && up[i][j] + 1 < i){
                dd[up[i][j]][j].push_back(mp(i, j));
            }
        }
    }
    for(int i = 0 ; i < m; i ++ ){
        L[i].init(n,1);
        R[i].init(n,0);
        for(int j = 0 ; j < n; j ++ ){
            R[i].upd(j,rig[j][i]);
            L[i].upd(j,lef[j][i]);
        }
    }
    for(int i = 0 ; i < n; i ++ ){
        U[i].init(m,1);
        D[i].init(m,0);
        for(int j = 0 ; j < m ; j ++ ){
            U[i].upd(j, up[i][j]);
            D[i].upd(j, dow[i][j]);
            sort(dd[i][j].begin(), dd[i][j].end());
            dd[i][j].resize(unique(dd[i][j].begin(), dd[i][j].end()) - dd[i][j].begin());
            sort(rr[i][j].begin(), rr[i][j].end());
            rr[i][j].resize(unique(rr[i][j].begin(), rr[i][j].end()) - rr[i][j].begin());
        }
    }
    int answ = 0;
    for(int i = 1 ; i < n; i ++ ){
        for(int j = 0 ; j + 1 < m ; j ++ ){
            for(auto x : rr[i][j]){
                for(auto y : dd[i - 1][j + 1]){
                    answ += is_valid(i - 1, j, y.fi, x.se);
                }
            }
        }
    }
    return answ;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...