DTOJ#5164. 鬼淵傳說
題面暫缺。
題解:
首先,對於不合法,有兩種情況,分別處理。
①內含白色連通塊。此時
O
(
n
2
)
O(n^2)
O(n2) 暴搜所有白色連通塊以及最小包含子矩形。可以發現,答案矩形不能包含子矩形。這時考慮優化
O
(
n
4
)
O(n^4)
O(n4) 暴力。
我們只用列舉上、下、左邊界,最大右邊界可以發現對於左邊界是單調增的。這時我們用桶維護。
②包含兩個及以上的黑色連通塊。這時我們可以發現對於兩列
r
r
r 和
r
+
1
r+1
r+1,假如我們把這兩列合併,可以發現若右邊界滿足①,那麼和並這兩列一定是合法的,不然必須有白色連通塊內含。所以我們可以算出
Δ
s
z
\Delta sz
Δsz 的字首和,就可以支援
O
(
1
)
O(1)
O(1) 查詢左端點的答案。
#include<bits/stdc++.h>
#define N 305
using namespace std;
inline int read(){
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
return x*f;
}
int a[N][N],b[N][N],n,m,lx,ly,rx,ry,flag,st;
char s[N];
struct node{
int sx,sy,tx,ty;
}sq[N*N];
inline bool cmp(node a,node b){return a.sx<b.sx;}
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
inline int pd(int x,int y){
return x>=1&&x<=n&&y>=1&&y<=m;
}
void dfs(int x,int y){
b[x][y]=1;
lx=min(lx,x);ly=min(y,ly);
rx=max(rx,x);ry=max(ry,y);
for(int i=0;i<4;++i){
int tx=x+dx[i],ty=y+dy[i];
if(a[tx][ty])continue;
if(!pd(tx,ty)){flag=1;continue;}
if(b[tx][ty])continue;
dfs(tx,ty);
}
}
int ccl[N][N],fa[N*N*3],cnt1[N],cnt2[N],sum[N],tong[N*N<<1],zero=N*N,tl[N];
inline int id1(int x,int y){
return (x-1)*m+y;
}
inline int id2(int x,int y,int typ){
return (typ+1)*id1(n,m)+(x-1)*m+y;
}
inline int get(int x){return (fa[x]==x)?x:fa[x]=get(fa[x]);}
long long ans;
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i){
scanf("%s",1+s);
for(int j=1;j<=m;++j){
a[i][j]=s[j]-'0';
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(a[i][j]==0&&!b[i][j]){
lx=n+1,ly=m+1,rx=0,ry=0;flag=0;
dfs(i,j);
if(!flag){
sq[++st].sx=lx,sq[st].sy=ly,sq[st].tx=rx,sq[st].ty=ry;
}
}
}
}
sort(sq+1,sq+1+st,cmp);
for(int ux=1,top=1;ux<=n;++ux){
for(int i=1;i<=m;++i)cnt1[i]=cnt2[i]=0;
for(int i=ux;i<=n;++i)for(int j=1;j<=m;++j)ccl[i][j]=1e9;
for(int i=ux;i<=n;++i)for(int j=1;j<=m;++j)fa[id1(i,j)]=id1(i,j),fa[id2(i,j,0)]=id2(i,j,0),fa[id2(i,j,1)]=id2(i,j,1);
for(int i=1;i<=m;++i)tl[i]=m;
while(sq[top].sx<=ux&&top<=st)++top;
for(int dx=ux,j=top;dx<=n;++dx){
while(j<=st&&sq[j].sx<=dx){
ccl[sq[j].tx+1][sq[j].sy-1]=min(ccl[sq[j].tx+1][sq[j].sy-1],sq[j].ty);
++j;
}
for(int i=1;i<=m;++i){
tl[i]=min(tl[i],ccl[dx][i]);
}
for(int i=m-1;i;--i)tl[i]=min(tl[i],tl[i+1]);
for(int i=1;i<=m;++i){
if(!a[dx][i])continue;
if(a[dx][i])cnt1[i]++;
if(a[dx-1][i]&&dx>ux){
fa[get(id1(dx,i))]=get(id1(dx-1,i));
cnt1[i]--;
//cout<<sq[j].sx<<" "<<sq[j].sy<<" "<<sq[j].tx<<" "<<sq[j].ty<<endl;
}
}
for(int i=2;i<=m;++i){
//if(ux==1&&dx==4)cout<<i<<" "<<get(20)<<endl;
//if(ux==1&&dx==4&&i==m)cout<<get(id2(dx,i))<<" "<<fa[id2(dx-1,i)]<<" "<<get(31)<<endl;
if(a[dx][i-1]){
cnt2[i]++;
if(a[dx-1][i-1]&&dx>ux){
fa[get(id2(dx,i-1,i&1))]=get(id2(dx-1,i-1,i&1));
cnt2[i]--;
}
}
if(a[dx][i]){
cnt2[i]++;
if(a[dx-1][i]&&dx>ux){
fa[get(id2(dx,i,i&1))]=get(id2(dx-1,i,i&1));
cnt2[i]--;
}
}
if(a[dx][i-1]&&a[dx][i]){
int fl=get(id2(dx,i-1,i&1)),fr=get(id2(dx,i,i&1));
if(fl!=fr){
fa[fl]=fr;
cnt2[i]--;
}
}
sum[i]=cnt2[i]-cnt1[i-1];
}
for(int i=2;i<=m;++i)sum[i]+=sum[i-1];
int l=m,r=m;
for(;l;--l){
tong[sum[l]+zero]++;
while(r>tl[l]&&r)tong[sum[r]+zero]--,--r;
ans+=tong[sum[l]-cnt1[l]+1+zero];
}
while(r)tong[sum[r]+zero]--,--r;
//memset(tong,0,sizeof(tong));
//for(int i=1;i<=m;++i)cout<<ux<<" "<<dx<<" "<<i<<":"<<f[ux][dx][i]<<endl;
/*if(ux==1&&dx==4){
for(int i=1;i<=m;++i)cout<<cnt2[i]<<" ";cout<<endl;
}*/
}
}
printf("%lld\n",ans);
return 0;
}
相關文章
- 淺說:網路空間擬態防禦是個什麼鬼?
- 銀河英雄傳說
- 關於鬼神傳說
- 傳說中的WindowManager
- 說一說 Laravel 郵件傳送流程Laravel
- 聽說node.js很火?那麼這skr什麼鬼東西?Node.js
- 《煉仙傳說》開啟預約——放手去修仙,躺贏變傳說
- 空指標的傳說指標
- 說說在 Python 中如何向函式傳參Python函式
- 面試官:兄弟,說說Java到底是值傳遞還是引用傳遞面試Java
- 說說不知道的Golang中引數傳遞Golang
- 遊戲,墜入深淵遊戲
- 『心善淵』Selenium3.0基礎 — 19、使用Selenium操作檔案的上傳和下載
- UILayer是什麼鬼UI
- 爐石傳說對決模式怎麼玩?爐石傳說對決模式玩法介紹模式
- 銀河英雄傳說(並查集)並查集
- 都說搭部落格簡單,鬼知道後端程式設計師要經歷什麼!後端程式設計師
- 說說在 Python 中如何傳遞任意數量的實參Python
- 簡單說說vue的父子元件,父子元件傳值和vuexVue元件
- 鬼玩意,看了就來氣
- pyc是個什麼鬼?
- 傳說中的資料結構_JAVA資料結構Java
- EMC傳動裝置設計說明
- 傳說中的“謂詞越界“場景
- 爐石傳說酒館戰棋姐夫好用嗎?爐石傳說的傑弗里斯英雄打法介紹
- 田淵棟:博士五年總結
- cross-env 是什麼鬼ROS
- where 1=1 是什麼鬼?
- SaaS,PaaS,IaaS都是什麼鬼
- 三體之後銀河紀元傳說
- laravel 郵件傳送功能使用說明Laravel
- 為什麼說Java中只有值傳遞。Java
- 程式猿生存指南-39 潛龍出淵
- c# 呼叫 C++ dll 傳入傳出型別對應說明(轉)C#C++型別
- P1196 [NOI2002] 銀河英雄傳說
- 設計漫談:傳說任務的曲折道路
- 深度分析,《弓箭傳說》如何長線運營(下)
- 深度分析,《弓箭傳說》如何長線運營(上)