제출 #285661

#제출 시각아이디문제언어결과실행 시간메모리
285661MKopchevRectangles (IOI19_rect)C++14
100 / 100
4457 ms571980 KiB
#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 l,int r) { for(int i=ST-1;i>=ADD;i--) { int where=i-ADD; if(where<r)tree_down[id][i]=bigger_down[id][where]; else tree_down[id][i]=1e9; } for(int i=ADD-1;i>=1;i--) { tree_down[id][i]=min(tree_down[id][i*2],tree_down[id][i*2+1]); } } int query_down(int id,int node,int l,int r,int lq,int rq) { lq=lq+ADD; rq=rq+ADD; while(lq<=rq) { if(tree_down[id][lq]<=WANTED_AT_MOST)return 1; if(tree_down[id][rq]<=WANTED_AT_MOST)return 1; lq=(lq+1)/2; rq=(rq-1)/2; } 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 l,int r) { for(int i=ST-1;i>=ADD;i--) { int where=i-ADD; if(where<r)tree_right[id][i]=bigger_right[where][id]; else tree_right[id][i]=1e9; } for(int i=ADD-1;i>=1;i--) { tree_right[id][i]=min(tree_right[id][i*2],tree_right[id][i*2+1]); } } int query_right(int id,int node,int l,int r,int lq,int rq) { lq=lq+ADD; rq=rq+ADD; while(lq<=rq) { if(tree_right[id][lq]<=WANTED_AT_MOST)return 1; if(tree_right[id][rq]<=WANTED_AT_MOST)return 1; lq=(lq+1)/2; rq=(rq-1)/2; } 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,0,m-1); } for(int j=0;j<m;j++) { build_right(j,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 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...