XJOI contest 1570 Problem B
阿新 • • 發佈:2020-10-07
這道題是我考場上唯一有把握的一道題,結果文體兩開花,時空雙爆炸……
題意
給你一個 \(n\times m\) 的 \(01\) 矩陣,同時還有 \(k\) 個操作,每一次操作會使得一個位置的 \(0\) 變成 \(1\) ,詢問每一個操作後矩陣的最大的全為 \(0\) 的正方形子矩陣邊長。
題解
我們可以定義一種狀態 \(f_{i,j}\) 表示以點 \((i,j)\) 作為正方形右下角時,最長的正方形邊長。對於一開始的矩陣,我們不難用 \(O(n^2)\) 的時間來求出這個東西,然後我們考慮修改。
我們發現,如果我們在 \((i,j)\) 這個位置改 \(0\) 變 \(1\) ,我們會使得之後的節點的 \(f{i,j}\)
\(0pts\) 程式碼如下:
#include<bits/stdc++.h> using namespace std; const int N=2005,K=2005; int n,m,k; bool mp[N][N]; int d[N][N]; struct Seg_Tree { int now=1; struct Node{int ls,rs,data,tag;}tr[4105]; void up(int u){tr[u].data=max(tr[tr[u].ls].data,tr[tr[u].rs].data);} void updata(int u,int z) { tr[u].data=min(tr[u].data,z); tr[u].tag=min(tr[u].tag,z); } void down(int u) { updata(tr[u].ls,tr[u].tag); updata(tr[u].rs,tr[u].tag); tr[u].tag=1e9+7; } void build(int u,int l,int r,int a[]) { tr[u].tag=1e9+7; if(l==r){tr[u].data=a[l];return;} int mid=(l+r)>>1; tr[u].ls=++now; build(tr[u].ls,l,mid,a); tr[u].rs=++now; build(tr[u].rs,mid+1,r,a); up(u); } void change(int u,int l,int r,int x,int y,int z) { if(x<=l&&r<=y){updata(u,z);return;} int mid=(l+r)>>1; down(u); if(x<=mid) change(tr[u].ls,l,mid,x,y,z); if(y>mid) change(tr[u].rs,mid+1,r,x,y,z); up(u); } }; struct Chg{int x,y,z;}; struct Seg_Tree_2 { int now=1; struct Node{int ls,rs;Seg_Tree data;vector<Chg> tag;}tr[4105]; void up(int u) { if(tr[tr[u].ls].data.tr[1].data>tr[tr[u].rs].data.tr[1].data) tr[u].data=tr[tr[u].ls].data; else tr[u].data=tr[tr[u].rs].data; } void updata(int u,Chg z) { tr[u].data.change(1,1,m,z.x,z.y,z.z); tr[u].tag.push_back(z); } void down(int u) { for(int i=0;i<tr[u].tag.size();++i) { updata(tr[u].ls,tr[u].tag[i]); updata(tr[u].rs,tr[u].tag[i]); } vector<Chg> ept; tr[u].tag.swap(ept); } void build(int u,int l,int r) { if(l==r){tr[u].data.build(1,1,m,d[l]);return;} int mid=(l+r)>>1; tr[u].ls=++now; build(tr[u].ls,l,mid); tr[u].rs=++now; build(tr[u].rs,mid+1,r); up(u); } void change(int u,int l,int r,int x,int y,Chg z) { if(x<=l&&r<=y){updata(u,z);return;} int mid=(l+r)>>1; down(u); if(x<=mid) change(tr[u].ls,l,mid,x,y,z); if(y>mid) change(tr[u].rs,mid+1,r,x,y,z); up(u); } }t; int main() { cin>>n>>m>>k; for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { char c;cin>>c; mp[i][j]=(c=='X'); } } for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { if(mp[i][j]) continue; d[i][j]=min(d[i-1][j]+1,d[i][j-1]+1); if(d[i-1][j]==d[i][j-1]&&mp[i-d[i][j]+1][j-d[i][j]+1]) d[i][j]--; } } // for(int i=1;i<=n;++i) // { // for(int j=1;j<=m;++j) // printf("%d ",d[i][j]); // printf("\n"); // } t.build(1,1,n); for(int i=1,x,y;i<=k;++i) { scanf("%d%d",&x,&y); for(int j=0;j<=max(n-x,m-y);++j) t.change(1,1,n,x,x+j,Chg{y,y+j,j}); printf("%d\n",t.tr[1].data.tr[1].data); } }