제출 #1126788

#제출 시각아이디문제언어결과실행 시간메모리
1126788VinhLuuRectangles (IOI19_rect)C++20
100 / 100
1621 ms506380 KiB
#include <bits/stdc++.h>
#define ll long long
#define all(lpv) lpv.begin(), lpv.end()
#define pot(x, y) lower_bound(x.begin(), x.end(), y) - x.begin() + 1
using namespace std;

//#define lpv

#ifndef lpv
#include "rect.h"
#endif // lpv

const int N = 3e3 + 5;
const int oo = 1e8;

int n, m, a[N][N], f[2][N << 1][N];
ll ans;

vector<int> col[N][N];

int get(int t,int l,int r,int x) {
  r++;
  int ret = oo;
  for(l += n - 1, r += n - 1; l < r; l /= 2, r /= 2) {
    if(l & 1) ret = min(ret, f[t][l ++][x]);
    if(r & 1) ret = min(ret, f[t][-- r][x]);
  }
  return ret;
}

long long count_rectangles(std::vector<std::vector<int>> _a) {
  n = _a.size();
  m = _a[0].size();
  for(int i = 1; i <= n; i ++) {
    for(int j = 1; j <= m; j ++) a[i][j] = _a[i - 1][j - 1];
  }

  for(int i = 1; i <= n; i ++) {
    stack<int> st;
    st.push(0);
    a[i][0] = oo;
    for(int j = 1; j <= m; j ++) {
      while(!st.empty() && a[i][st.top()] < a[i][j]) st.pop();
      int x = (st.top() == 0 ? 1 : st.top());
      f[0][i + n - 1][j] = j - x;
      st.push(j);
    }

    while(!st.empty()) st.pop();
    st.push(m + 1);
    a[i][m + 1] = oo;
    for(int j = m; j >= 1; j --) {
      while(!st.empty() && a[i][st.top()] < a[i][j]) st.pop();
      int x = (st.top() == m + 1 ? m : st.top());
//      if(i == 3 && j == 1) cerr << x << " " << x - j << " " <<  << " g\n";
      f[1][i + n - 1][j] = x - j;
      st.push(j);
    }
  }

  for(int j = 1; j <= m; j ++) {
    for(int i = n - 1; i >= 1; i --) for(int t = 0; t <= 1; t ++) {
      f[t][i][j] = min(f[t][i << 1][j], f[t][i << 1|1][j]);
    }
  }

  for(int j = 2; j < m; j ++) {
    stack<int> st;
    st.push(0);
    a[0][j] = oo;
    for(int i = 1; i <= n; i ++) {
      while(!st.empty() && a[st.top()][j] < a[i][j]) st.pop();
      int x = st.top();
      if(x && x != i - 1) col[i][x].push_back(j);
      st.push(i);
    }

    while(!st.empty()) st.pop();
    st.push(n + 1);
    a[n + 1][j] = oo;
    for(int i = n; i >= 1; i --) {
      while(!st.empty() && a[st.top()][j] < a[i][j]) st.pop();
      int x = st.top();

      if(x != n + 1 && x != i + 1) {
        col[x][i].push_back(j);
//        if(j == 4) cerr << x << " " << i << " " << j << " o\n";
      }
      st.push(i);
    }
  }

  for(int r = 1; r <= n; r ++) {


//    if(r != 3) continue;


    for(int l = r - 2; l >= 1; l --) if(!col[r][l].empty()) {
      sort(all(col[r][l])); col[r][l].resize(unique(all(col[r][l])) - col[r][l].begin());
//      cerr << r << " " << l << " t\n";
//      for(auto j : col[r][l]) cerr << j << " ";
//      cerr << "\n";
      int pre = -1, last = -1;
      for(auto i : col[r][l]) {
        if(pre == -1) pre = i;
        else if(i > last + 1) pre = i;
        last = i;
        int val = get(0, l + 1, r - 1, i + 1);
        int pos = i + 1 - val;
//        if(i == 4) cerr << l + 1 << " " << r - 1 << " " << i + 1 << " " << pos << " " << pre << " t\n";
        if(pos >= pre - 1 && pos != i) {
          int tmp = get(1, l + 1, r - 1, pos);
          if(pos + tmp >= i + 1) {
            ans++;
//            cerr << pos << " " << i + 1 << " " << l + 1 << " " << r - 1 << " x1\n";
          }
        }
      }
      pre = -1, last = -1;
      reverse(all(col[r][l]));
      for(auto i : col[r][l]) {
        if(pre == -1) pre = i;
        else if(i < last - 1) pre = i;
        last = i;
        int val = get(1, l + 1, r - 1, i - 1);
        int pos = i - 1 + val;
        if(pos <= pre + 1 && pos != i) {
          int tmp = get(0, l + 1, r - 1, pos);
          if(pos - tmp < i - 1) {
            ans++;
//            cerr << i - 1 << " " << pos << " " << l + 1 << " " << r - 1 << " h\n";
          }
        }
      }
//      cerr << l << " " << ans << " g\n";
    }
//    cerr << r << " " << ans << " f\n";
  }

  cerr << ans << "\n";

  return ans;
}

/*

6 6
2 13 15 14 12 15
17 6 8 3 10 2
6 18 16 20 13 12
4 4 4 20 19 13
5 12 12 2 10 17
9 9 3 17 9 19


6 5
4 8 7 5 6
7 4 10 3 5
9 7 20 14 2
9 14 7 3 6
5 7 5 2 7
4 5 13 5 6

*/


#ifdef lpv
signed main() {
  ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  #define task "v"
  if(fopen(task ".inp","r")) {
    freopen(task ".inp","r",stdin);
    freopen(task ".out","w",stdout);
  }
  int _n, _m;cin >> _n >> _m;
  vector<vector<int>> _a;
  for(int i = 1; i <= _n; i ++) {
    vector<int> tmp;
    for(int j = 1; j <= _m; j ++) {
      int x; cin >> x;
      tmp.push_back(x);
    }
    _a.push_back(tmp);
  }
  cout << count_rectangles(_a);
}
#endif // lpv
#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...