Submission #1285940

#TimeUsernameProblemLanguageResultExecution timeMemory
1285940MMihalevSoccer Stadium (IOI23_soccer)C++20
2 / 100
4614 ms444656 KiB
#include<iostream>
#include<vector>
#include<algorithm>
#include<tuple>
#include<queue>
#include<set>
#include "soccer.h"
using namespace std;
const int MAX_N=2e3+3;
int n;
int a[MAX_N][MAX_N];
int p[MAX_N][MAX_N];
int lastok[2][MAX_N][MAX_N];//0 : back  |  1 : forward
set<int>block[MAX_N];

bool allempty(int x1,int y1,int x2,int y2)
{
    int x11=min(x1,x2),x22=max(x1,x2);
    int y11=min(y1,y2),y22=max(y1,y2);
    x1=x11+1;y1=y11+1;x2=x22+1;y2=y22+1;
    if(p[x2][y2]-p[x1-1][y2]-p[x2][y1-1]+p[x1-1][y1-1]==(x2-x1+1)*(y2-y1+1))return 1;
    return 0;
}

int tree[2][2][MAX_N][4*MAX_N];
int lazy[2][2][MAX_N][4*MAX_N];
void push_lazy(int topbottom,int dir,int node,int l,int r,int row)
{
    tree[topbottom][dir][row][node]=max(tree[topbottom][dir][row][node],lazy[topbottom][dir][row][node]);
    if(l!=r)
    {
        lazy[topbottom][dir][row][2*node]=max(lazy[topbottom][dir][row][2*node],lazy[topbottom][dir][row][node]);
        lazy[topbottom][dir][row][2*node+1]=max(lazy[topbottom][dir][row][2*node+1],lazy[topbottom][dir][row][node]);
    }
    lazy[topbottom][dir][row][node]=0;
}
void update(int topbottom,int dir,int node,int l,int r,int row,int ql,int qr,int val)
{
    push_lazy(topbottom,dir,node,l,r,row);
    if(r<ql or l>qr)return;
    if(ql<=l && r<=qr)
    {
        lazy[topbottom][dir][row][node]=max(lazy[topbottom][dir][row][node],val);
        push_lazy(topbottom,dir,node,l,r,row);
        return;
    }
    int mid=(l+r)/2;
    update(topbottom,dir,2*node,l,mid,row,ql,qr,val);
    update(topbottom,dir,2*node+1,mid+1,r,row,ql,qr,val);
    tree[topbottom][dir][row][node]=max(tree[topbottom][dir][row][2*node],tree[topbottom][dir][row][2*node+1]);
}
int query(int topbottom,int dir,int node,int l,int r,int row,int idx)
{
    push_lazy(topbottom,dir,node,l,r,row);
    if(r<idx or l>idx)return -1;
    if(l==r)
    {
        return tree[topbottom][dir][row][node];
    }
    int mid=(l+r)/2;
    return max(query(topbottom,dir,2*node,l,mid,row,idx),query(topbottom,dir,2*node+1,mid+1,r,row,idx));
}

void rowupdate(int topbottom,int row,int leftborder,int rightborder,int cur)
{
    auto it=block[row].lower_bound(leftborder);
    int first=(*(it));
    if(first>rightborder+1)return;
    auto it2=block[row].upper_bound(rightborder);
    int last=(*(it2));
    if(last>rightborder+1)
    {
        it2--;
    }
    last=(*(it2));

    if(leftborder<=last-1)update(topbottom,1,1,0,n-1,row,leftborder,last-1,cur);
    if(first+1<=rightborder)update(topbottom,0,1,0,n-1,row,first+1,rightborder,cur);
}

vector<tuple<int,int,bool>>states[MAX_N];
int solve()
{
    int ans=1;

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(a[i][j])continue;

            int l=j,r=lastok[1][i][j];
            states[r-l+1].push_back({i,j,1});
            l=lastok[0][i][j];r=j;
            states[r-l+1].push_back({i,j,0});
        }
    }
    for(int len=1;len<=n;len++)sort(states[len].rbegin(),states[len].rend());

    for(int len=n;len>=1;len--)
    {
        for(auto [row,col,dir]:states[len])
        {
            int leftborder=min(col,lastok[dir][row][col]),rightborder=max(col,lastok[dir][row][col]);

            int l=row,r=n-1;
            int row2;
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(allempty(row,leftborder,mid,rightborder))
                {
                    row2=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }

            int cur=len+query(0,dir,1,0,n-1,row,col);
            ans=max(ans,cur);

            if(row-1>=0)rowupdate(0,row-1,leftborder,rightborder,cur);
            if(row2+1<n)rowupdate(1,row2+1,leftborder,rightborder,cur);
        }
        ///minimum at the top


        reverse(states[len].begin(),states[len].end());
        for(auto [row,col,dir]:states[len])
        {
            int leftborder=min(col,lastok[dir][row][col]),rightborder=max(col,lastok[dir][row][col]);

            int l=0,r=row;
            int row2;
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(allempty(mid,leftborder,row,rightborder))
                {
                    row2=mid;
                    r=mid-1;
                }
                else l=mid+1;
            }

            int cur=len+query(1,dir,1,0,n-1,row,col);
            ans=max(ans,cur);

            if(row2-1>=0)rowupdate(0,row2-1,leftborder,rightborder,cur);
            if(row+1<n)rowupdate(1,row+1,leftborder,rightborder,cur);
        }
        ///minimum at the bottom
    }
    return ans;
}
int biggest_stadium(int N, std::vector<std::vector<int>> F)
{
    n=N;
    for(int i=0;i<n;i++)
    {
        block[i].insert(-1);
        block[i].insert(n);
        for(int j=0;j<n;j++)
        {
            a[i][j]=F[i][j];
            if(a[i][j])block[i].insert(j);
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            p[i][j]=(a[i-1][j-1]==0)+p[i-1][j]+p[i][j-1]-p[i-1][j-1];
        }
    }

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(a[i][j])continue;
            if(j==0 or a[i][j-1])
            {
                lastok[0][i][j]=j;
                continue;
            }
            lastok[0][i][j]=lastok[0][i][j-1];
        }
        for(int j=n-1;j>=0;j--)
        {
            if(a[i][j])continue;
            if(j==n-1 or a[i][j+1])
            {
                lastok[1][i][j]=j;
                continue;
            }
            lastok[1][i][j]=lastok[1][i][j+1];
        }
    }

    return solve();
}
#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...