Submission #293318

#TimeUsernameProblemLanguageResultExecution timeMemory
293318rqiRectangles (IOI19_rect)C++14
100 / 100
3740 ms386076 KiB
#include "rect.h"
#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;

template<class K,class V> using ht = gp_hash_table<
    K,
    null_type,
    hash<K>,
    equal_to<K>,
    direct_mask_range_hashing<>,
    linear_probe_fn<>,
    hash_standard_resize_policy<
      hash_exponential_size_policy<>,
      hash_load_check_resize_trigger<>,
      true
    >
>;

 
typedef long long ll;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vpi;
 
const int MOD = 1000000007;
 
#define ins insert
#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define all(x) begin(x), end(x)
#define bk back()
 
const int mx = 2505;
int n, m;
 
ht<int, null_type> ints2[mx];
 
vector<pair<int, pi>> queries[mx];
vector<pair<int, pi>> updates[mx];

vpi res;
vi R;
vi cur;
 
vpi getInts(const vi &a){
	// cout << "Q: ";
	// for(auto u: a) cout << u << " ";
	// cout << "\n";

	res.clear();

	R = vi(sz(a), -1);
	cur.clear();
	for(int i = sz(a)-1; i >= 0; i--){
		while(sz(cur)){
			if(a[cur.bk] <= a[i]){
				cur.pop_back();
			}
			else break;
		}
		if(sz(cur)) R[i] = cur.bk;
		cur.pb(i);
	}
	cur.clear();
	for(int i = 0; i < sz(a); i++){
		while(sz(cur)){
			if(a[cur.bk] <= a[i]){
				cur.pop_back();
			}
			else break;
		}
		int L = -1;
		if(sz(cur)) L = cur.bk;
		cur.pb(i);
		if(R[i] != -1 && L != -1){
			res.pb(mp(L+1, R[i]-1));
		}
	}

	// vpi vals;
	// for(int i = 0; i < sz(a); i++){
	// 	vals.pb(mp(a[i], i));
	// }
	// sort(vals.rbegin(), vals.rend());

	// set<int> poses;
	// for(int i = 0; i < sz(vals); i++){
	// 	auto it1 = poses.lb(vals[i].s);
	// 	if(sz(poses) >= 2 && it1 != poses.end() && it1 != poses.begin()){
	// 		int p1 = *(prev(it1));
	// 		int p2 = *it1;
	// 		if(vals[i].f < min(a[p1], a[p2])){
	// 			res.pb(mp(p1+1, p2-1));
	// 		}
	// 	}
	// 	poses.ins(vals[i].s);
	// }

	// for(int i = 0; i < sz(vals); i++){
	// 	pair<pi, pi> b = *(prev(rang.lb(mp(mp(vals[i].s, MOD), mp(0, 0)))));
	// 	//cout << i << "\n";
	// 	assert(b.f.f <= vals[i].s && vals[i].s <= b.f.s);
	// 	rang.erase(b);
	// 	//if vals[i] is the max in range & if not on boundary
	// 	if(vals[i].f < min(b.s.f, b.s.s) && 1 <= b.f.f && b.f.s <= sz(a)-2){
	// 		res.pb(b.f);
	// 	}
	// 	//only divide if range added
	// 	if(b.f.f <= vals[i].s-1){
	// 		rang.ins(mp(mp(b.f.f, vals[i].s-1), mp(b.s.f, vals[i].f)));
	// 	}
	// 	if(vals[i].s+1 <= b.f.s){
	// 		rang.ins(mp(mp(vals[i].s+1, b.f.s), mp(vals[i].f, b.s.s)));
	// 	}
	// }
 
	// cout << "R: ";
	// for(auto u: res) cout << "(" << u.f << " " << u.s << "), ";
	// cout << "\n";
	return res;
}
 
int val[mx];
vi curin;
 
void upd(int a, int v){
	if(v == 1) curin.pb(a);
	for(; a < mx; a+=a&-a) val[a]+=v;
}
 
int sum(int a){
	int res = 0;
	for(; a > 0; a-=a&-a) res+=val[a];
	return res;
}
 
int query(int a, int b){
	return sum(b)-sum(a-1);
}
 
void clearBIT(){
	for(auto u: curin){
		upd(u, -1);
	}
	curin.clear();
}
 
ll count_rectangles(vector<vi> a){
	// clock_t c = clock();
	// cout << fixed << setprecision(5);
	// cout << double(clock()-c)/CLOCKS_PER_SEC << "\n";
	n = sz(a);
	m = sz(a[0]);
	// double r1 = 0;
	// double r2 = 0;
	for(int i = 1; i+1 < n; i++){
		vi nums;
		for(int j = 0; j < m; j++){
			nums.pb(a[i][j]);
		}
		
		// clock_t d = clock();
		vpi a = getInts(nums);
		// r1+=double(clock()-d)/CLOCKS_PER_SEC;
		// d = clock();
		for(auto u: a){
			ints2[i].ins(mx*u.f+u.s);
		}
		// r2+=double(clock()-d)/CLOCKS_PER_SEC;
		// d = clock();
	}
	// cout << "r1: " << r1 << "\n";
	// cout << "r2: " << r2 << "\n";
 	// cout << double(clock()-c)/CLOCKS_PER_SEC << "\n";
	ht<int, null_type> vals;
 
	for(int i = 1; i+1 < n; i++){
		vals = ints2[i];
		for(auto x: vals){
			int j = x/mx;
			int u = x % mx;
			for(int K = i; K+1 < n; K++){
				if(ints2[K+1].find(mx*j+u) == ints2[K+1].end()){
					for(int k = i; k <= K; k++){
						queries[k].pb(mp(j, mp(K, u)));
						//cout << "Q: " << k << " " << j << " " << K << " " << u << "\n";
						ints2[k].erase(mx*j+u);
					}
					break;
				}
			}
		}
	}
 	// cout << double(clock()-c)/CLOCKS_PER_SEC << "\n";
	for(int i = 0; i < mx; i++){
		ints2[i].clear();
	}
 
	for(int j = 1; j+1 < m; j++){
		//cout << "j: " << j << "\n";
		vi nums;
		for(int i = 0; i < n; i++){
			nums.pb(a[i][j]);
		}
		vpi a = getInts(nums);
		// cout << "a: " << "\n";
		// for(auto u: a){
		// 	cout << u.f << " " << u.s << "\n";
		// }
		for(auto u: a){
			ints2[j].ins(mx*u.f+u.s);
			//ints[u.f][j].ins(u.s);
		}
	}
 
	
	for(int j = 1; j+1 < m; j++){
		vals = ints2[j];
		for(auto x: vals){
			int i = x/mx;
			int u = x % mx;
			for(int K = j; K+1 < m; K++){
				if(ints2[K+1].find(mx*i+u) == ints2[K+1].end()){
					for(int k = j; k <= K; k++){
						updates[i].pb(mp(k, mp(u, K)));
						//cout << "U: " << i << " " << k << " " << u << " " << K << "\n";
						//cout << i << " " << j << " " << k << "\n";
						ints2[k].erase(mx*i+u);
					}
					break;
				}
			}
		}
	}
 	
 	// cout << double(clock()-c)/CLOCKS_PER_SEC << "\n";

	ll ans = 0;
 
	for(int i = 1; i+1 < n; i++){
		sort(all(queries[i]));
		sort(all(updates[i]));
		int updind = 0;

		int lasty = -1;

		for(auto u: queries[i]){
			if(u.f != lasty) clearBIT();
			while(updind < sz(updates[i])){
				if(updates[i][updind].f < u.f){
					updind++;
					continue;
				}
				if(updates[i][updind].f > u.f){
					break;
				}
				if(updates[i][updind].s.f <= u.s.f){
					upd(updates[i][updind].s.s, 1);
					updind++;
					continue;
				}
				else break;
			}
			ans+=query(u.s.s, 2504);
			lasty = u.f;
		}

		// for(int j = 1; j+1 < m; j++){
		// 	sort(all(queries[i][j]));
		// 	sort(all(updates[i][j]));
		// 	int updind = 0;
		// 	for(auto u: queries[i][j]){
		// 		while(updind < sz(updates[i][j])){
		// 			if(updates[i][j][updind].f <= u.f){
		// 				upd(updates[i][j][updind].s, 1);
		// 				updind++;
		// 			}
		// 			else break;
		// 		}
		// 		//if(query(u.s, 2504) > 0) cout << i << " " << j << "\n";
		// 		ans+=query(u.s, 2504); //number of things >=
		// 	}
		// 	clearBIT();
		// }
	}
 	// cout << double(clock()-c)/CLOCKS_PER_SEC << "\n";
	return ans;
}
#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...