Submission #1196852

#TimeUsernameProblemLanguageResultExecution timeMemory
1196852MateiKing80Rectangles (IOI19_rect)C++20
100 / 100
1916 ms803544 KiB
#include "rect.h"
#include <bits/stdc++.h>

using namespace std;

const int N = 2600;

int n, m, w[N][N], T[N];
vector<int>Right[N][N], Down[N][N];

int st[N], RR[N], LL[N];

void PreCalc(int n) {
	int top = 0;
	for (int i = 1; i <= n; i ++)
		RR[i] = LL[i] = 0;
	for (int i = 1; i <= n; i ++) {
		while (top && T[st[top]] <= T[i]) {
			RR[st[top]] = i;
			top --;
		}
		st[++ top] = i;
	}
	top = 0;
	for (int i = n; i >= 1; i --) {
		while (top && T[st[top]] <= T[i]) {
			LL[st[top]] = i;
			top--;
		}
		st[++top] = i;
	}
}

int last[N][N], CC[N][N];
int lastH[N], CH[N];

struct point {
	int x, y, ck;
	bool operator < (const point &p) const {
		return x < p.x;
	}
} U[10100];

int BIT[N];

void Add(int a, int b) {
	while (a <= m) {
		BIT[a] += b;
		a += a & -a;
	}
}
int Sum(int a) {
	int r = 0;
	while (a) {
		r += BIT[a];
		a -= a & -a;
	}
	return r;
}

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

	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= m; j ++)
			T[j] = w[i][j];
		PreCalc(m);
		for (int j = 1; j <= m; j ++) {
			if (RR[j] && RR[j] > j + 1)
				Right[i][j + 1].push_back(RR[j] - 1);
			if (LL[j] && LL[j] < j - 1 && RR[LL[j]] != j)
				Right[i][LL[j] + 1].push_back(j - 1);
		}
	}
	for (int i = 1; i <= m; i ++) {
		for (int j = 1; j <= n; j ++)
			T[j] = w[j][i];
		PreCalc(n);
		for (int j = 1; j <= n; j ++) {
			if (RR[j] && RR[j] > j + 1)
				Down[j + 1][i].push_back(RR[j] - 1);
			if (LL[j] && LL[j] < j - 1 && RR[LL[j]] != j)
				Down[LL[j] + 1][i].push_back(j - 1);
		}
	}
	long long res = 0;
	for (int i = n; i >= 1; i --) {
		for (int j = 1; j <= n; j ++)
			lastH[j] = CH[j] = 0;
		for (int j = m; j >= 1; j--) {
			for (auto &t : Right[i][j]) {
				if (last[j][t] != i + 1)
					CC[j][t] = 0;
				CC[j][t] ++;
				last[j][t] = i;
			}
			for (auto &t : Down[i][j]) {
				if (lastH[t] != j + 1)
					CH[t] = 0;
				CH[t] ++;
				lastH[t] = j;
			}
			int cnt = 0;
			for (auto &t : Right[i][j]) {
				U[cnt ++] = {i, t, 1};
				U[cnt ++] = {i + CC[j][t], t, -1};
			}
			sort(U, U + cnt);
			sort(Down[i][j].begin(), Down[i][j].end());
			int pv = 0;
			for (auto &t : Down[i][j]) {
				while (pv < cnt && U[pv].x <= t) {
					Add(U[pv].y, U[pv].ck);
					pv ++;
				}
				res += Sum(j + CH[t] - 1);
			}
			while (pv < cnt) {
				Add(U[pv].y, U[pv].ck);
				pv ++;
			}
		}
	}
	return res;
}
#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...