SHOI2015 零件組裝機

2021-10-10 07:25:14 字數 1879 閱讀 5336

[shoi2015]零件組裝機

同機房大佬想性質想了很久,我從樹的思想搞很快搞出來了

言歸正傳,這道題目從樹的思路想是比較簡單的,關鍵是建樹。

現在講講建樹:對於一條邊,預設是從編號大的連向編號小的有向邊。

那麼,設x

xx連向的編號最大的點為y

yy,那麼x,y

x,yx,

y是什麼關係?

我們規定乙個聯通塊的根為這個聯通塊編號最小的點(不難發現聯通塊的編號是連續的),那麼x,y

x,yx,

y的關係其實就是以x

xx為根的聯通塊與[y,

x−1]

[y,x-1]

[y,x−1

]的聯通塊合併。

這樣,我們就只需要根據x,y

x,yx,

y建出一棵樹,從下往上合併,每次合併檢驗一下即可。

需要注意的是:如果存在重邊和自環直接無解。

當然還有乙個性質:合法圖的邊的是在o(n

)o(n)

o(n)

級別的。(同機房大佬找到的)

時間複雜度:o((

n+m)

log⁡m)

o((n+m)\log)

o((n+m

)logm)

用桶排加記憶體池以及其餘細節便可以優化到o(n

+m

)o(n+m)

o(n+m)

#include

#include

#include

#include

#define n 110000

using

namespace std;

set<

int> ****[n]

;int cnt,now;

//合法邊的數量

int fa[n]

,siz[n]

;int id[n]

;inline

bool

cmp(

int x,

int y)

inline

bool

check

(int l1,

int r1,

int l2,

int r2)

//檢驗吧[l2,r2]合併到[l1,r1]是否合法

return0;

}int n,m;

intmain()

set<

int>

::iterator ****=****[x]

.find

(y);

if(****==****[x]

.end()

)//重邊無解

else bk=1;

}for

(int i=

0;i)id[i]

=i; siz[0]

=1;for

(int i=

1;i) set<

int>

::iterator x=****[i]

.end()

; x--

;fa[i]

=*x;}if

(bk==1)

for(

int i=n-

1;i>=

1;i--

)siz[fa[i]]+

=siz[i]

;sort

(id,id+n,cmp)

;for

(int i=

0;i1;i++)}

if(bk==

1|| now!=cnt)

printf

("yes\n");

}return0;

}

SHOI2015 超能粒子炮 改

設 f n k sum kc n i pmod 那麼根據盧卡斯定理我們知道 f n k sum kc times c c 0 times sum c i c 1 times sum c i c times sum c i c times sum c i sum c i times c 0 c 1 c...

SHOI2015 自動刷題機

我也想要乙個!顯然能夠看出來單調性 當n越大,能ac的題越少,反之越少。所以。很明顯的二分答案對吧。唯一一點不太一樣的是,它要求可能的最大值,和可能的最小值。那我們就寫兩個check,先求出來最大值,如果算出來的ac題數大於等於k,我們就選擇右區間。然後再0和最大值的區間中再次二分 減小帶的log的...

SHOI2015 超能粒子炮 改

求 sum 2333 n,k leq 10 如果直接套盧卡斯還是比較容易想到分塊求解的 由 c n i c times c 可知,i p 相同的組合數另一部分分別是 i p,i p 1,i p 2.這部分可以搓到一起 令 s n k sum 具體來說,將這部分相同的部分放到一起,剩下的地方直接計算 ...