長長的屋子

2021-08-02 15:10:24 字數 1623 閱讀 1619

小林要搬家啦!

小林把家搬到了乙個長長的屋子裡,屋子裡一共有n個房間連成一排,從左到右依次標號為1…n。每兩個相鄰的房間之間都有一扇門,門上有一把鎖,第i個房間和第i+1個房間之間的鎖型別為ci。為了防止康娜胡鬧,小林把鑰匙都藏在了房間裡,第i個房間裡放了bi把鑰匙,鑰匙的種類分別為ai[1],ai[2],…,ai[bi]。注意,每把鑰匙只能開啟對應型別的鎖,同一種型別可能存在多把鑰匙和多把鎖,鑰匙開鎖後不會消失。

但是這樣仍然不能阻止康娜胡鬧,因此,小林會在康娜睡著的時候把康娜移動到別的房間裡去。在接下來的q天裡,第i天,康娜醒來的時候會發現自己身處第xi個房間裡,而她想要到第yi個房間裡去。

康娜不知道自己能不能到達第yi個房間,請你幫助她計算出,她能否在第xi個房間出發,拾取到達房間的所有鑰匙並開啟對應的鎖,最終到達第yi個房間。

設a[i]表示從i出發能到達的區間。

如果i能到達j,有a[i]包含a[j]。

如果i和j能互達,有a[i]=a[j]。

預處理開每扇門所需要鑰匙在這扇門往左往右的第乙個房間。

這樣可以快速判斷已有乙個區間的鑰匙能不能開某扇門。

接下來記憶化搜尋。我們用並查集表示a相同的點。

假如在搜尋j,拓展到k。

若k已經搜過了,a[j]=a[j] or a[k]。

若k已經搜到了,我們用並查集縮j和k並退出當前搜尋。

若k未搜過,我們搜尋k。

這樣的複雜度是對的,因為任意一扇門只會開一次。

#include

#include

#include

#define fo(i,a,b) for(i=a;i<=b;i++)

#define fd(i,a,b) for(i=a;i>=b;i--)

using namespace std;

const int maxn=500000+10;

int left[maxn],right[maxn],last[maxn],c[maxn];

int h[maxn],go[maxn],next[maxn];

int fa[maxn],sta[maxn],l[maxn],r[maxn];

bool bz[maxn],pd[maxn];

int i,j,k,l,r,t,n,m,tot,top,cnt,x,y;

intread()

while (ch>='0'&&ch<='9')

return

x*f;

}void add(int

x,int

y)int getfa(int

x)void merge(int

x,int

y)int main()

l[i]=r[i]=i;

}fo(i,1,n) last[i]=n+1;

fd(i,n,1)

}fo(i,1,n) last[i]=0;

fo(i,1,n)

}fo(i,1,n)

if (!bz[getfa(i)])

if (bz[y])

else

if (pd[y])

else}}

m=read();

while (m--)

}

那些長長短短的句子

多想有個機會,能躲在角落裡哭。待鉛華洗淨,趨於平淡,你仍在白髮蒼蒼的年齡裡惦念,我又何德何能。你治不了的相思病,是我寫不出的南國夢。我是你的紅藥水 他是你的黑咖啡 我會問你累不累 他卻讓你不能睡 我的句子成不成詩已無所謂,只留待有心人回味。為你傷春悲秋埋種憾事 為你踏不出這綿延萬里的幼稚情緒 天涼無...

屋子裡有1到100號100盞關閉的燈

屋子裡有1到100號100盞關閉的燈,門外有1到100號100個人,每個人都要進屋一次,把與自己序號對應的和是自己序號倍數的燈繩拉一下,比如1號要拉所有的燈繩,2號要拉2,4,6的燈繩,而100號只需拉100號燈繩 問 當100人都出來後,屋子裡亮著的燈有幾盞?這麼說呢,大家都知道答案是 平方數 1...

Oracle表記錄位元組長長度的兩種計算方式

oracle表記錄位元組長長度的兩種計算方式 一 獲取某個使用者下某個錶行記錄的長度 這個長度是表字段定義的長度,獲取方法 select owner,table name,column name,data type,data length,sum case data type when date t...