#include "rect.h"
#include <bits/stdc++.h>
using namespace std;
struct coor{
short r,c;
coor(){
r=c=0;
}
coor(short x,short y){
r=x;c=y;
}
};
struct segment{
short r,R,c,C;
segment(){
r=c=-1;R=C=8192;
}
segment(short x,short X,short y,short Y){
r=x;R=X;c=y;C=Y;
}
};
vector<set<short>> rowset,colset;
vector<vector<coor>> countvec;
vector<pair<int,coor>> vec;
vector<vector<segment>> grid;
vector<segment> seg;
segment merge(segment a,segment b){
segment ans;
ans.r=min(a.r,b.r);
ans.c=min(a.c,b.c);
ans.R=max(a.R,b.R);
ans.C=max(a.C,b.C);
return ans;
}
void build(int id,coor l,coor r){
if(l.r==r.r){
seg[id]=grid[l.r][l.c];
return;
}
coor m=coor((l.r+r.r)/2,(l.c+r.c)/2);
build(id*4,l,m);
build(id*4+1,coor(m.r+1,l.c),coor(r.r,m.c));
build(id*4+2,coor(l.r,m.c+1),coor(m.r,r.c));
build(id*4+3,coor(m.r+1,m.c+1),r);
seg[id]=merge(merge(seg[id*4],seg[id*4+1]),merge(seg[id*4+2],seg[id*4+3]));
}
void update(int id,coor l,coor r,coor x,segment c){
if(l.r==r.r){
seg[id]=c;
return;
}
coor m=coor((l.r+r.r)/2,(l.c+r.c)/2);
if(x.r<=m.r){
if(x.c<=m.c){
update(id*4,l,m,x,c);
seg[id]=merge(seg[id],seg[id*4]);
}else{
update(id*4+2,coor(l.r,m.c+1),coor(m.r,r.c),x,c);
seg[id]=merge(seg[id],seg[id*4+2]);
}
}else if(x.c<=m.c){
update(id*4+1,coor(m.r+1,l.c),coor(r.r,m.c),x,c);
seg[id]=merge(seg[id],seg[id*4+1]);
}else{
update(id*4+3,coor(m.r+1,m.c+1),r,x,c);
seg[id]=merge(seg[id],seg[id*4+3]);
}
// seg[id]=merge(merge(seg[id*4],seg[id*4+1]),merge(seg[id*4+2],seg[id*4+3]));
}
segment query(int id,coor l,coor r,coor L,coor R){
if(r.r<L.r||r.c<L.c||l.r>R.r||l.c>R.c){
return segment(8192,-1,8192,-1);
}else if(l.r>=L.r&&l.c>=L.c&&r.r<=R.r&&r.c<=R.c){
return seg[id];
}
coor m=coor((l.r+r.r)/2,(l.c+r.c)/2);
return merge(merge(query(id*4,l,m,L,R),query(id*4+1,coor(m.r+1,l.c),coor(r.r,m.c),L,R)),merge(query(id*4+2,coor(l.r,m.c+1),coor(m.r,r.c),L,R),query(id*4+3,coor(m.r+1,m.c+1),r,L,R)));
}
//8000*8000->128MB*4->512MB
//100MB
long long count_rectangles(vector<vector<int> > a) {
int n=a.size(),m=a[0].size();
long long ans=0;
vec.resize(n*m);countvec.resize(7000009);rowset.resize(n);colset.resize(m);seg.resize(8200*8200);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
vec[i*m+j]={a[i][j],coor(i,j)};
countvec[a[i][j]].push_back(coor(i,j));
rowset[i].insert(j);
colset[j].insert(i);
}
}
sort(vec.begin(),vec.end(),[](pair<int,coor> A,pair<int,coor> B){
return A.first<B.first;
});
grid.resize(4100,vector<segment>(4100,segment()));
build(1,coor(0,0),coor(4095,4095));
for(int i=0;i<n*m;i++){
int r=vec[i].second.r,c=vec[i].second.c;
for(auto u:countvec[a[r][c]]){
rowset[u.r].erase(u.c);
colset[u.c].erase(u.r);
}
countvec[a[r][c]].clear();
auto u=colset[c].lower_bound(r);
if(u==colset[c].end()){
grid[r][c].R=n-1;
}else{
grid[r][c].R=(*u)-1;
}
if(u==colset[c].begin()){
grid[r][c].r=0;
}else{
grid[r][c].r=(*--u)+1;
}
u=rowset[r].lower_bound(c);
if(u==rowset[r].end()){
grid[r][c].C=m-1;
}else{
grid[r][c].C=(*u)-1;
}
if(u==rowset[r].begin()){
grid[r][c].c=0;
}else{
grid[r][c].c=(*--u)+1;
}
update(1,coor(0,0),coor(4095,4095),coor(r,c),grid[r][c]);
bool can=(grid[r][c].r>0&&grid[r][c].R<n-1&&grid[r][c].c>0&&grid[r][c].C<m-1);
if(can){
segment tmp=query(1,coor(0,0),coor(4095,4095),coor(grid[r][c].r,grid[r][c].c),coor(grid[r][c].R,grid[r][c].C));
if(tmp.r>=grid[r][c].r&&tmp.c>=grid[r][c].c&&tmp.R<=grid[r][c].R&&tmp.C<=grid[r][c].C){
ans++;
}
}
}
return ans;
}
//step 1: find r,R,c,C Currently:O(n)
//step 2: update grid[r][c] Currently:O(1)
//step 3: query subrectangle (r,c) to (R,C) Currently:O(n*m)
//step 3.1: check if unvisited
//step 3.2: find minimum r,c
//step 3.3: find maximum R,C
//step 4: update ans Currently:O(1)
//set -> step1: lg(n) done
//2D segtree -> step 2: lg(n), step 3: lg(n)^2
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |