이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include "rect.h"
#include<bits/stdc++.h>
using namespace std;
const int nmax=2500+42,ST=1<<13,ADD=1<<12;
int bigger_up[nmax][nmax],bigger_down[nmax][nmax],bigger_right[nmax][nmax],bigger_left[nmax][nmax];
int tree_up[nmax][ST];
int WANTED_AT_LEAST,WANTED_AT_MOST;
void build_up(int id,int l,int r)
{
for(int i=ST-1;i>=ADD;i--)
{
int where=i-ADD;
if(where<r)tree_up[id][i]=bigger_up[id][where];
}
for(int i=ADD-1;i>=1;i--)
{
tree_up[id][i]=max(tree_up[id][i*2],tree_up[id][i*2+1]);
}
}
int query_up(int id,int node,int l,int r,int lq,int rq)
{
lq=lq+ADD;
rq=rq+ADD;
while(lq<=rq)
{
if(tree_up[id][lq]>=WANTED_AT_LEAST)return 1;
if(tree_up[id][rq]>=WANTED_AT_LEAST)return 1;
lq=(lq+1)/2;
rq=(rq-1)/2;
}
return 0;
}
int tree_down[nmax][ST];
void build_down(int id,int node,int l,int r)
{
if(l==r)
{
tree_down[id][node]=bigger_down[id][l];
return;
}
int av=(l+r)/2;
build_down(id,node*2,l,av);
build_down(id,node*2+1,av+1,r);
tree_down[id][node]=min(tree_down[id][node*2],tree_down[id][node*2+1]);
}
int fast_down_left(int id,int node,int l,int r,int lq,int rq)
{
while(tree_down[id][node]<=WANTED_AT_MOST)
{
if(l==lq&&r==rq)return 1;
int av=(l+r)/2;
if(av<lq)
{
l=av+1;
node=node*2+1;
continue;
}
if(tree_down[id][node*2+1]<=WANTED_AT_MOST)return 1;
node=node*2;
r=av;
rq=av;
}
return 0;
}
int fast_down_right(int id,int node,int l,int r,int lq,int rq)
{
while(tree_down[id][node]<=WANTED_AT_MOST)
{
if(l==lq&&r==rq)return 1;
int av=(l+r)/2;
if(rq<=av)
{
r=av;
node=node*2;
continue;
}
if(tree_down[id][node*2]<=WANTED_AT_MOST)return 1;
node=node*2+1;
l=av+1;
lq=av+1;
}
return 0;
}
int query_down(int id,int node,int l,int r,int lq,int rq)
{
//cout<<"query_down "<<id<<" "<<node<<" "<<l<<" "<<r<<" "<<lq<<" "<<rq<<endl;
while(tree_down[id][node]<=WANTED_AT_MOST)
{
if(l==lq&&r==rq)return 1;
int av=(l+r)/2;
if(rq<=av)
{
node=node*2;
r=av;
continue;
}
if(av<lq)
{
node=node*2+1;
l=av+1;
continue;
}
if(fast_down_left(id,node*2,l,av,lq,av))return 1;
return fast_down_right(id,node*2+1,av+1,r,av+1,rq);
}
return 0;
}
int tree_left[nmax][ST];
void build_left(int id,int l,int r)
{
for(int i=ST-1;i>=ADD;i--)
{
int where=i-ADD;
if(where<r)tree_left[id][i]=bigger_left[where][id];
}
for(int i=ADD-1;i>=1;i--)
{
tree_left[id][i]=max(tree_left[id][i*2],tree_left[id][i*2+1]);
}
}
int query_left(int id,int node,int l,int r,int lq,int rq)
{
lq=lq+ADD;
rq=rq+ADD;
while(lq<=rq)
{
if(tree_left[id][lq]>=WANTED_AT_LEAST)return 1;
if(tree_left[id][rq]>=WANTED_AT_LEAST)return 1;
lq=(lq+1)/2;
rq=(rq-1)/2;
}
return 0;
}
int tree_right[nmax][ST];
void build_right(int id,int node,int l,int r)
{
if(l==r)
{
tree_right[id][node]=bigger_right[l][id];
return;
}
int av=(l+r)/2;
build_right(id,node*2,l,av);
build_right(id,node*2+1,av+1,r);
tree_right[id][node]=min(tree_right[id][node*2],tree_right[id][node*2+1]);
}
int fast_right_left(int id,int node,int l,int r,int lq,int rq)
{
while(tree_right[id][node]<=WANTED_AT_MOST)
{
if(l==lq&&r==rq)return 1;
int av=(l+r)/2;
if(av<lq)
{
l=av+1;
node=node*2+1;
continue;
}
if(tree_right[id][node*2+1]<=WANTED_AT_MOST)return 1;
node=node*2;
r=av;
rq=av;
}
return 0;
}
int fast_right_right(int id,int node,int l,int r,int lq,int rq)
{
while(tree_right[id][node]<=WANTED_AT_MOST)
{
if(l==lq&&r==rq)return 1;
int av=(l+r)/2;
if(rq<=av)
{
r=av;
node=node*2;
continue;
}
if(tree_right[id][node*2]<=WANTED_AT_MOST)return 1;
node=node*2+1;
l=av+1;
lq=av+1;
}
return 0;
}
int query_right(int id,int node,int l,int r,int lq,int rq)
{
//cout<<"query_right "<<id<<" "<<node<<" "<<l<<" "<<r<<" "<<lq<<" "<<rq<<endl;
while(tree_right[id][node]<=WANTED_AT_MOST)
{
if(l==lq&&r==rq)return 1;
int av=(l+r)/2;
if(rq<=av)
{
node=node*2;
r=av;
continue;
}
if(av<lq)
{
node=node*2+1;
l=av+1;
continue;
}
if(fast_right_left(id,node*2,l,av,lq,av))return 1;
return fast_right_right(id,node*2+1,av+1,r,av+1,rq);
}
return 0;
}
stack<int> active,idle;
int pointer=0;
struct rect
{
int x1,y1,x2,y2;
};
rect to_test[nmax*nmax];
bool cmp(rect a,rect b)
{
if(a.x1!=b.x1)return a.x1<b.x1;
if(a.y1!=b.y1)return a.y1<b.y1;
if(a.x2!=b.x2)return a.x2<b.x2;
return a.y2<b.y2;
}
bool eq(rect a,rect b)
{
return a.x1==b.x1&&a.y1==b.y1&&a.x2==b.x2&&a.y2==b.y2;
}
int n,m;
bool test(rect a)
{
//cout<<"to test "<<a.x1<<" "<<a.y1<<" "<<a.x2<<" "<<a.y2<<endl;
WANTED_AT_LEAST=a.x1;
if(query_up(a.x2+1,1,0,m-1,a.y1,a.y2))return 0;
WANTED_AT_MOST=a.x2;
if(query_down(a.x1-1,1,0,m-1,a.y1,a.y2))return 0;
WANTED_AT_LEAST=a.y1;
if(query_left(a.y2+1,1,0,n-1,a.x1,a.x2))return 0;
WANTED_AT_MOST=a.y2;
if(query_right(a.y1-1,1,0,n-1,a.x1,a.x2))return 0;
return 1;
}
vector< vector<int> > inp;
void eval(int type)//1=> bigger, 0=> bigger or equal
{
n=inp.size();
m=inp[0].size();
for(int i=0;i<n;i++)
{
active=idle;
for(int j=0;j<m;j++)
{
while(active.size()&&inp[i][active.top()]+type<=inp[i][j])active.pop();
if(active.size())bigger_left[i][j]=active.top();
else bigger_left[i][j]=-1;
active.push(j);
}
}
for(int i=0;i<n;i++)
{
active=idle;
for(int j=m-1;j>=0;j--)
{
while(active.size()&&inp[i][active.top()]+type<=inp[i][j])active.pop();
if(active.size())bigger_right[i][j]=active.top();
else bigger_right[i][j]=m;
active.push(j);
}
}
for(int j=0;j<m;j++)
{
active=idle;
for(int i=0;i<n;i++)
{
while(active.size()&&inp[active.top()][j]+type<=inp[i][j])active.pop();
if(active.size())bigger_up[i][j]=active.top();
else bigger_up[i][j]=-1;
active.push(i);
}
}
for(int j=0;j<m;j++)
{
active=idle;
for(int i=n-1;i>=0;i--)
{
while(active.size()&&inp[active.top()][j]+type<=inp[i][j])active.pop();
if(active.size())bigger_down[i][j]=active.top();
else bigger_down[i][j]=n;
active.push(i);
}
}
}
long long count_rectangles(std::vector<std::vector<int> > a)
{
inp=a;
int n=inp.size();
int m=inp[0].size();
eval(0);
/*
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cout<<i<<" "<<j<<" -> "<<bigger_up[i][j]<<" "<<bigger_right[i][j]<<" "<<bigger_down[i][j]<<" "<<bigger_left[i][j]<<endl;
}
*/
pointer=0;
for(int i=1;i<n-1;i++)
for(int j=1;j<m-1;j++)
{
rect cur;
cur.x1=bigger_up[i][j]+1;
cur.y1=bigger_left[i][j]+1;
cur.x2=bigger_down[i][j]-1;
cur.y2=bigger_right[i][j]-1;
//cout<<i<<" "<<j<<" -> "<<cur.x1<<" "<<cur.y1<<" "<<cur.x2<<" "<<cur.y2<<endl;
if(1<=cur.x1&&cur.x2<=n-2&&1<=cur.y1&&cur.y2<=m-2)
{
pointer++;
to_test[pointer]=cur;
}
}
sort(to_test+1,to_test+pointer+1,cmp);
eval(1);
for(int i=0;i<n;i++)
{
build_up(i,0,m-1);
build_down(i,1,0,m-1);
}
for(int j=0;j<m;j++)
{
build_right(j,1,0,n-1);
build_left(j,0,n-1);
}
int outp=0;
for(int i=1;i<=pointer;i++)
{
if(eq(to_test[i-1],to_test[i]))continue;
outp+=test(to_test[i]);
}
return outp;
}
# | 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... |