FJOI省隊集訓 florida

2022-02-02 06:52:32 字數 2560 閱讀 5537

省隊成員(大部分)都沒來...像我這種沙茶天天寫寫玄學演算法都能排在榜上面...果然正解寫掛的人遠比暴力拍對的人少啊...陸陸續續會補一些題解。(不過有些題太神了可能補不上題解

有n個物品,兩個袋子a和b。若物品i與j放在同乙個袋子裡,那麼代價為t[i][j],保證t[i][i]=0,t[i][j]=t[j][i]。

乙個袋子的代價d=袋子中兩兩物品代價的最大值。你需要將物品分配到兩個袋子中,最小化d(a)+d(b)。

2<=n<=250,0<=t[i][j]<=10^9。

陳旭大爺有一種暴力倍增的做法可以跑過去...跪爛

我們不妨設d(a)<=d(b),那麼我們列舉d(b),顯然可以二分d(a)判可行性。

對於兩物品i,j,如果d(a)d(b),那麼i和j就不能放在一起。

所以這就成了乙個2-sat問題,可以用經典的tarjan做法解決。

這樣是o(n^4logn)的,由於過於玄學只能得到部分分。

這個做法看起來已經十分優秀了,要怎麼優化呢?

我們發現列舉d(b)看起來就不太靠譜,真的要列舉o(n^2)種取值嗎?

顯然不要,我們考慮搞出一棵最大生成樹,以t為邊權。接下來考慮對這棵生成樹黑白染色,如果乙個集合b包括了兩種顏色的點,那麼顯然d(b)就是最大生成樹上的邊(可以由kruskal演算法的正確性得到)。否則b只包括一種顏色的點,只包含所有白點或只包含所有黑點(為什麼是所有點呢?因為如果是部分點,那麼a肯定包括另一種顏色的全部點。由於是最大生成樹,那麼d(a)>d(b))。所以我們只要嘗試這些d(b)即可。

這樣似乎就是o(n^3logn)的。

我們可以加一些奇技淫巧來優化,我的做法是將權值離散二分,然後每次根據最優解隨便剪剪枝,這樣就可以過了。

#include #include 

#include

#include

#include

using

namespace

std;

#define sz 666

int n,t[sz][sz],ls[sz*sz],ln=0,en=0

;int

ff[sz];

int gf(int

x)int m=0,fst[sz*sz*5],vb[sz*sz*5],nxt[sz*sz*5

];void ad_de(int a,int b)

void adde(int a,int

b) struct edg es[sz*sz];

bool

operator

< (edg a,edg b)

int ds[sz*sz],dn=0

;int

col[sz];

void dfs(int x,int

c)//

tarjan

namespace

tjvoid adde(int a,int

b) int ss[sz],sn=0,low[sz],dfn[sz],cnt=0,bl[sz],scc=0

;bool

ins[sz];

void

init()

void tarjan(int

x)

else

if(ins[b]) low[x]=min(low[x],dfn[b]);

}if(dfn[x]!=low[x]) return

;

int p; ++scc;

dowhile(p!=x);}}

bool ok(int da,int

db)

else

if(t>da)}}

for(int i=2;i<=2*n+1;i++)

for(int i=1;i<=n;i++) if(tj::bl[i*2]==tj::bl[i*2+1]) return0;

return1;

}struct f}__("

florida");

intmain()

for(int i=1;i<=n;i++)

sort(ls+1,ls+1+ln); ln=unique(ls+1,ls+1+ln)-ls-1

;

for(int i=1;i<=n;i++)

sort(es+1,es+1+en);

for(int i=1;i<=n;i++)

for(int i=1;i<=en;i++)

dfs(

1,0);

int maxn[2]=;

for(int i=1;i<=n;i++)

}ds[++dn]=maxn[0]; ds[++dn]=maxn[1

]; sort(ds+1,ds+1+dn); dn=unique(ds+1,ds+1+dn)-ds-1

;

int ans=2000000033

;

for(int i=0;i<=dn;i++)

ans=min(ans,ls[db]+ls[l]);

}printf(

"%d\n

",ans);

main();

}

7 5省隊集訓 tree

思路 樹形dp。先求最大值。令s x 為x的子樹中葉子節點的數量。f x 為到x時 為先手走,先手能取到的值在子樹中排第f x 小。g x 為到x時 為後手走,後手能取到的值在子樹中排第f x 小。對f x 先手應該往哪個子樹走呢?對於x的一棵子樹y,如果進入,那麼最終答案就是這棵子樹中第g y 小...

7 10省隊集訓夢工廠

思路 題面真心長.單調棧維護上凸殼即可 設sum i 為前i道工序的複雜度之和,g i 為第i個快樂最早開始生產的時間。因為我們要保證沒有兩個快樂同時出現在同一道工序,所以 g i g i 1 max sum j f i 1 sum j 1 f i 然後就是像斜率優化的過程了 sum j f i 1...

省隊集訓DAY2

假設我們列舉數列中長度為len的區間,那麼如何判斷兩個數列可以匹配呢?對於提取的數列從小到大排序,從大到小排序,然後兩兩配對,如果所有的都滿足 h 那麼就可以匹配。應該算是貪心吧。這樣做的時間複雜度是o n le n loglen 還是上面的思想,我們如何快速判斷呢?假設我們確定了提取出的區間數列,...