君君演算法課堂 好題分享1

2022-09-10 07:21:09 字數 3521 閱讀 6120

tarzan 非常煩數軸因為數軸上的題總是難度非常大。不過他非常喜歡線段,因為有關線

段的題總是不難,諷刺的是在乙個數軸上有 n 個線段,tarzan 希望自己喜歡的東西和討厭的

東西不在一起,所以他要把這些線段分多次帶走,每一次帶走一組,最多能帶走 k 次。其實

就是要把這些線段分成至多 k 組,每次帶走一組,問題遠沒有那麼簡單,tarzan 還希望每次

選擇的線段組都很有相似性,我們定義一組線段的相似性是組內線段交集的長度,我們現在

想知道最多分成 k 個組帶走,tarzan 最多能得到的相似性之和是多少?

第一行兩個整數 n 和 k。

接下來 n 行每行兩個整數 li, ri 表示線段的左右端點。

一行乙個整數,表示最多能得到的相似性之和是多少。

input 1

5 3

5 10

4 11

6 910 30

20 40

output 1
43
input 2
5 3 

5 11

16 22

14 20

10 20

6 10

output 2
18
input 3
7 3 

1 92 9

2 10

5 15

3 14

14 18

16 20

output 3
21
對於 20% 的資料滿足:\(n ≤ 8; k ≤ 5\)

對於 40% 的資料滿足:\(k, n ≤ 12\);

對於 70% 的資料滿足:\(n ≤ 100\),

對於 100% 的資料滿足:\(1 ≤ k ≤ n ≤ 6000, 1 ≤ li < ri ≤ 10^6\);

對於 \(\%20\) 的資料,直接列舉每乙個線段在哪乙個集合裡面即可

時間複雜度:\(o(k^n)\)

對於 \(\%40\) 的資料,\(dfs\) 搜尋每一條線段在哪乙個集合裡面,

進行適當剪枝後可以得到最高 \(40\) 分的部分分,

對於 \(\%70\) 的資料,首先,手玩樣例一番,收集性質如下:

①空集組(對答案無貢獻)最多只有一組。

證明:若有\(k(k >= 2)\)組空集, 則在這些集合中找出前\(k-1\)條線段放入乙個集合, 另外的線段放入剩下的乙個集合可增加選出來的\(k-1\)條線段長度的答案貢獻。

性質①得證。

②若沒有空集的話,可以再觀察到乙個性質:

對於完全包含另乙個線段b的線段a, 則b與a在一組可能會使答案更優(但不一定),不優的情況會在下文另行考慮。

證明:根據題意可得,對於給出的\(n\)條線段,每條線段都會屬於乙個集合。

設長度為\(x\)的線段被長度為\(y(y > x)\)的線段包含。

因 \(x\)被\(y\)包含,所以\(x\)與\(y\)分到一組,則\(x\)所在集合對答案的貢獻最大為\(x\)。

而若\(x\)與不包含\(x\)的線段分到一組時,在小的方面來說答案不優(整體來看可能更優)。

性質②得證。

下面對於性質②的缺陷作考慮:

性質②是將\(x\)與\(y\)放到乙個集合,那我們未考慮到的情況就是\(x\)與\(y\)相分離的情況。

我們考慮\(x\)與\(y\)相分離時怎樣最優。

顯然當\(y\)單獨乙個集合時對答案的貢獻最大。

當然,上面情況成立的條件是仍有空的集合未被使用。

注:當產生包含關係後,\(y\)對集合已無貢獻。

所以我們才可以將\(x\)與\(y\)進行分離操作。

否則,演算法正確性無法得以保證。

此時,再結合性質①,對答案無貢獻的集合最多只有乙個。

我們便有了一種做法:

優先考慮不包含的情況,再將\(x\)與\(y\)進行分離操作,更新答案。

因分離線段操作(只考慮包含別的線段的線段)不會對現有答案產生影響。

所以我們可以進行dp預處理操作。

將線段排序,挑選所有出\(r\)遞增且\(l\)遞增(不包含)的線段。

此時顯然能dp。

設\(f[i][j]\)為前\(i\)條線段選了\(j\)個集合相似度之和。

注:這\(j\)個集合不能有空集,因為我們要給每個空集分發線段,更新答案。

否則答案不優。

考慮第\(j\)個集合放入第\(x+1\sim i\)條線段,

則\(f[i][j]=max(f[x][j-1]+r[x+1]-l[i]|r[x+1]>l[i])\)

轉化方程得:\(f[i][j]=max(f[x][j-1]+r[x+1]|r[x+1]>l[i])-l[i]\)

對於 \(\%100\) 的資料,在 \(\%70\) 的資料的基礎上進行單調佇列優化。

考慮我們選擇了多少集合,設為\(p\),

考慮用包含其它線段的線段來更新答案。

則此情況對答案的貢獻為

\(f[n][p]\)+包含其它線段的前\(k-p\)長線段長度之和。

再列舉\(p\)取最優值即可。

時間複雜度:\(o(n^2)\),在空間上可以使用滾動陣列優化。

#include #include #include #include using namespace std;

const int n = 6e3 + 5;

int read()

struct edge t1[n], t2[n];

int n, k, ans, r, len[n], q[n], head, tail, maxl, tot, cnt, f[2][n];

bool cop(const edge &a, const edge &b)

int main()

else len[++ tot] = t1[i].r - t1[i].l;//r遞增l遞減,加入t1(說明這些線段有包含關係);

} sort(len + 1, len + tot + 1, greater());//長度從大到小排序 ;

for(int i = 2; i <= n; i ++) len[i] += len[i-1];//求包含其它線段的線段的長度字首和;

sort(t2 + 1, t2 + cnt + 1, cop);//這些線段不相互包含 ;

r = 1;//滾動陣列優化;

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

ans = max(ans, f[0][cnt] + len[k-1]);//1個集合 + (k - 1)個集合 ;

for(int j = 2; j <= min(k, cnt); j ++, r ^= 1)

ans = max(ans, f[r][cnt] + len[k - j]);//j個集合 + (k - j) 個集合

} cout << ans << endl;

return 0;

}

B君的第一題

1.1 題目大意 大概是個比較有趣的面試題。1.2 題目分析 首先考慮如何計算當前的勝率。這個有兩種演算法,動態規劃和組合數。1.3 動態規劃 假設當前甲贏了 i 場,乙贏了 j 場。如果 i n,那麼 fi,j 1。如果 j n,那麼 fi,j 0。對於一般情況,有 fi,j 1 2 fi 1,j...

6 1 好題分享小結

我好久沒寫部落格了啊懶惰病上線,這個歡樂的節日聽了ha最強女選手講課,於是決定翹掉地理課寫篇部落格總結一下 內容大致是中位數,先看一下圓神講課思路 這樣我可以少闡明很多概念 第乙個就是引例啦 貨倉選址 我們設在倉庫左邊的所有點,到倉庫的距離之和為p,右邊的距離之和則為q,那麼我們就必須讓p q的值盡...

2018 07 14 T3 B君的第六題

暫無鏈結 問題描述 丟掉幻想,準備鬥爭!輸入四個長度為 n n 的序列ai bi,ci,d i。role presentation style position relative ai,bi,c i,di ai,bi,c i,di 求這4 4 序列最長公共子串行的長度。公共子串行不需要連續。輸入格式...