제출 #285550

#제출 시각아이디문제언어결과실행 시간메모리
285550MKopchevRectangles (IOI19_rect)C++14
72 / 100
5122 ms351708 KiB
#include "rect.h"
#include<bits/stdc++.h>
using namespace std;

const int nmax=2500+42,ST=1<<13;

int bigger_up[nmax][nmax],bigger_down[nmax][nmax],bigger_right[nmax][nmax],bigger_left[nmax][nmax];

int tree_up[nmax][ST];

void build_up(int id,int node,int l,int r)
{
    if(l==r)
    {
        tree_up[id][node]=bigger_up[id][l];
        return;
    }
    int av=(l+r)/2;

    build_up(id,node*2,l,av);
    build_up(id,node*2+1,av+1,r);

    tree_up[id][node]=max(tree_up[id][node*2],tree_up[id][node*2+1]);
}
int query_up(int id,int node,int l,int r,int lq,int rq)
{
    //cout<<"query_up "<<id<<" "<<node<<" "<<l<<" "<<r<<" "<<lq<<" "<<rq<<endl;

    if(l==lq&&r==rq)return tree_up[id][node];

    int av=(l+r)/2;

    if(rq<=av)return query_up(id,node*2,l,av,lq,rq);
    if(av<lq)return query_up(id,node*2+1,av+1,r,lq,rq);

    return max(query_up(id,node*2,l,av,lq,av),query_up(id,node*2+1,av+1,r,av+1,rq));
}
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;

    if(query_up(a.x2+1,1,0,m-1,a.y1,a.y2)>=a.x1)return 0;

    for(int j=a.y1;j<=a.y2;j++)
    {
        //cout<<"j= "<<j<<endl;

        if(bigger_down[a.x1-1][j]<=a.x2)return 0;
        //if(bigger_up[a.x2+1][j]>=a.x1)return 0;
    }

    for(int i=a.x1;i<=a.x2;i++)
    {
        //cout<<"i= "<<i<<endl;

        if(bigger_right[i][a.y1-1]<=a.y2)return 0;
        if(bigger_left[i][a.y2+1]>=a.y1)return 0;
    }

    //cout<<"ok"<<endl;

    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,1,0,m-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...