jzoj P2249 蒸發學水

2021-08-13 15:32:35 字數 2955 閱讀 7013

機房的位置一共有n 行m 列,一開始每個位置都有一滴學水,terryhu 決定在每乙個時刻選擇

一滴學水進行蒸發,直到機房裡不再存在學水。

terryhu 想知道在每個時刻之後,機房裡剩下的學水構成了幾個聯通塊。

對於60% 的資料:n,m<= 50;

對於100% 的資料:n,m<= 1000。

鄰接表+並查集:

這題我們直接暴力的去做,很明顯只能過60分的點

即暴力的列舉,時間複雜度:o((nm)^2)

我們用鄰接表去記錄不同大小的數的位置

然後我們逆向思維地用並查集去做

我們從後往前即學水大到小依次加入,這樣我們就可以保證每次得到的ans[x]就是第x時刻的聯通塊數

對於每次加入的[x,y]

如果周邊沒有學水,那麼ans+1

如果周邊有學水,而且有y滴,那麼很明顯會想到ans-y+1,不過有y滴並不代表一定有y個聯通塊,因為y滴學水之間可能有相通的,這時候用並查集去處理即可。

const

dx:array [1..4] of longint=(1,-1,0,0);

dy:array [1..4] of longint=(0,0,-1,1);

var a:array [0..1001,0..1001] of longint;

f:array [0..1000001] of longint;

list:array [0..1000001,1..2] of longint;

fd,next:array [0..1001,0..1001,1..2] of longint;

mind:array [1..4] of boolean;

xx,yy,ans,x,y,i,j,k,n,m:longint;

procedure

find

(cx,cy:longint);

begin

if (fd[cx,cy,1]=cx) and (fd[cx,cy,2]=cy) then

begin

xx:=cx;

yy:=cy;

exit;

end;

find(fd[cx,cy,1],fd[cx,cy,2]);

fd[cx,cy,1]:=xx;

fd[cx,cy,2]:=yy;

end;

procedure

insert

(cx,cy:longint);

var i,j,k,d,x1,y1,x2,y2:longint;

begin

k:=0;

d:=0;

fillchar(mind,sizeof(mind),false);

for i:=1to4

doif a[cx+dx[i],cy+dy[i]]=1

then

begin

inc(k);

ifnot(mind[i]) then

begin

find(cx+dx[i],cy+dy[i]);

x1:=xx; y1:=yy;

for j:=1to4

doif (i<>j) and (not(mind[j])) and (a[cx+dx[j],cy+dy[j]]=1) then

begin

find(cx+dx[j],cy+dy[j]);

x2:=xx; y2:=yy;

if (x1=x2) and (y1=y2) then

begin

mind[i]:=true;

mind[j]:=true;

end;

end;

inc(d);

end;

end;

for i:=1to4

doif a[cx+dx[i],cy+dy[i]]=1

then

begin

find(cx+dx[i],cy+dy[i]);

fd[xx,yy,1]:=cx;

fd[xx,yy,2]:=cy;

end;

if d=0

then

begin

ans:=ans-k+1;

exit;

end;

ans:=ans-d+1;

end;

begin

assign(input,'evaporate.in'); reset(input);

assign(output,'evaporate.out'); rewrite(output);

readln(n,m);

for i:=1

to n do

begin

for j:=1

to m do

begin

read(k);

next[i,j,1]:=list[k,1];

next[i,j,2]:=list[k,2];

list[k,1]:=i;

list[k,2]:=j;

end;

readln;

end;

ans:=0;

for k:=n*m downto1do

begin

f[k]:=ans;

x:=list[k,1]; y:=list[k,2];

while x>0

dobegin

a[x,y]:=1;

fd[x,y,1]:=x;

fd[x,y,2]:=y;

i:=x; j:=y;

insert(x,y);

x:=next[i,j,1];

y:=next[i,j,2];

end;

end;

for i:=1

to n*m do writeln(f[i]);

close(input); close(output);

end.

2 24作業講解

1 編寫課上講解的有參裝飾器準備明天默寫 2 還記得我們用函式物件的概念,製作乙個函式字典的操作嗎,來來來,我們有更高大上的做法,在檔案開頭宣告乙個空字典,然後在每個函式前加上裝飾器,完成自動新增到字典的操作1 func dic 23 4 func dic 56 有參裝飾器 x接收的是使用者輸入功能...

藍橋杯 遞迴 2 24

回形取數 藍橋杯 基礎練習 問題描述 回形取數就是沿矩陣的邊取數,若當前方向上無數可取或已經取過,則左轉90度。一開始位於矩陣左上角,方向向下。輸入格式 輸入第一行是兩個不超過200的正整數m,n,表示矩陣的行和列。接下來m行每行n個整數,表示這個矩陣。輸出格式 輸出只有一行,共mn個數,為輸入矩陣...

藍橋杯 練習(2 24)

給定n個十六進製制正整數,輸出它們對應的八進位制數。輸入的第一行為乙個正整數n 1 n 10 接下來n行,每行乙個由09 大寫字母af組成的字串,表示要轉換的十六進製制正整數,每個十六進製制數長度不超過100000。輸出n行,每行為輸入對應的八進位制正整數。注意 輸入的十六進製制數不會有前導0,比如...