2020牛客暑期多校訓練營(第八場)IKG補題

2021-10-08 19:53:56 字數 4699 閱讀 7875

很顯然,每個客人都必須從第一道菜開始連續吃,那麼第一道菜的數目就是最大招待客人的數目。

之後就是如何求最大利潤。

由於每個人都必須連續吃菜,那麼後面的菜即使比前面的菜數量多也沒有意義。

我們可以直接預處理,將後面多的菜直接定義為等於前面的菜,形成乙個遞減序列

很顯然,最大利潤就是每一步都貪心地找最大字首和。

使用結構體排序,對每個字首和的數目(也就是結尾菜的數目)進行記錄,最後選擇b[1]數目個字首和即可。(b[1]為第一道菜的數目,也就是最大客人數)。

比較坑的一點,最終的答案會超過long long,群裡大佬建議使用__int128,由於我__int128的模板忽略了負數的情況,導致沒有ac,悔恨。

#include

using

namespace std;

const

int maxn =

1e5+50;

long

long a[maxn]

;long

long b[maxn]

;struct node

pos[maxn]

;bool

cmp(node a, node b)

void

print

(__int128 x)

if(x>9)

print

(x/10);

putchar

(x%10

+'0');

}int

main()

for(

int i =

1; i <= n; i++

)for

(int i =

1; i <= n; i++

) pos[i]

.sum = pos[i-1]

.sum + a[i]

; pos[i]

.id = i;

pos[i]

.num = b[i];}

sort

(pos+

1,pos+

1+n,cmp)

;int num =0;

for(

int i =

1; i <= n; i++

)printf

("case #%d: %lld "

,k,b[1]

);print

(ans)

;printf

("\n");

}return0;

}

圖論的直覺讓我覺得與圖有關。

將每個數對理解為兩個點直接有一條邊相連,選擇其中乙個點,意味著要給這條邊確定乙個方向。那麼對於連通塊,如果是和樹一樣,只有n-1條邊,那麼一定有乙個點的入度為0(沒有被選)。如果不是一棵樹,即邊數 >= n,那麼一定可以有一條邊指向起點。

so,對於每個連通塊,分為兩種情況:

1.連通塊的邊數 = n-1, 那麼ans += n-1;

2.連通塊的邊數 >= n,那麼ans += n;

注意,點的資料為e9,使用離散化以便使用陣列(過多使用map會t,別問為什麼,我試過了,嗚嗚嗚)

#include

#include

#include

using

namespace std;

const

int maxn =

2e5+50;

int fa[maxn]

;int dian[maxn]

;int a[maxn]

;int b[maxn]

;int

find

(int x)

void

hebing

(int x,

int y)

return;}

int num;

int bian[maxn]

;int

main()

for(

int i =

1; i <= num; i++

)for

(int i =

1; i <= n; i++

)for

(int i =

1; i <= n; i++)}

int ans =0;

for(

int i =

1; i <= num; i++)}

cout <<

"case #"

<< k <<

": "

; cout << ans << endl;

}}

組的定義:選擇3個物品,對於同一項屬性,三者完全相同,或者完全不同。

直接n的立方暴力會超時,256大。

題解的結論,當n超過21時,一定可以成組。隨意立方的暴力只需要暴力到21即可。

隊友想到了如果n比較大,那麼一定會成組,避免暴力256,但是沒求出具體數。

21的證明實在看不懂…

#include

#include

#include

using

namespace std;

const

int maxn =

2e5+50;

mapint> m;

struct node

a[maxn]

;int

judge

(int x,

int y,

int z)

else

if(a[x]

.a != a[y]

.a && a[x]

.a != a[z]

.a && a[y]

.a != a[z]

.a)else

if(a[x]

.a ==

4|| a[y]

.a ==

4|| a[z]

.a ==4)

else

if(a[x]

.b == a[y]

.b && a[x]

.b == a[z]

.b)else

if(a[x]

.b != a[y]

.b && a[x]

.b != a[z]

.b && a[y]

.b != a[z]

.b)else

if(a[x]

.b ==

4|| a[y]

.b ==

4|| a[z]

.b ==4)

else

if(a[x]

.c == a[y]

.c && a[x]

.c== a[z]

.c)else

if(a[x]

.c != a[y]

.c && a[x]

.c != a[z]

.c && a[y]

.c != a[z]

.c)else

if(a[x]

.c ==

4|| a[y]

.c ==

4|| a[z]

.c ==4)

else

if(a[x]

.d == a[y]

.d && a[x]

.d == a[z]

.d)else

if(a[x]

.d != a[y]

.d && a[x]

.d != a[z]

.d && a[y]

.d != a[z]

.d)else

if(a[x]

.d ==

4|| a[y]

.d ==

4|| a[z]

.d ==4)

else

return1;

}int

main()

else

break;}

for(j = j +

2; j < s.

length()

; j++

)else

break;}

for(j = j +

2; j < s.

length()

; j++

)else

break;}

for(j = j +

2; j < s.

length()

; j++

)else

break;}

a[i]

.a = m[a]

; a[i]

.b = m[b]

; a[i]

.c = m[c]

; a[i]

.d = m[d];}

cout <<

"case #"

<< k <<

": "

;int flag =0;

for(

int i =

1; i <=

min(n,21)

; i++)}

if(flag)

break;}

if(flag)

break;}

if(!flag) cout <<-1

<< endl;

}}

ps:這個題就算你直接n的立方,也可以ac,因為你列舉到21的時候就可以終止了。

2020牛客暑期多校訓練營(第八場)

題意 給出n對數,對於每一對,其中如果有沒有選過的數那麼就可以選,就可以選擇那乙個數,ans 需要求最大的ans 思路 隊友很強,思路秒出,十分鐘 一發ac可以把這些數對想成一條邊上的兩個點,可以想像一下如果我要最多的選擇這上面的點,假如這些點構成的邊是一棵樹的話,我們最多在這n個點中能選擇的只有n...

2020牛客暑期多校訓練營(第八場)

總結 這次做的不好,爆零了,雖然確實本場題比較難,但是沒做出來確實問題很大,考慮問題不夠全面仔細。kg 待定給出n對數字a,b。有三種操作。第一種,什麼也不做。第二種,如果ai在在前面沒有被選過,可以選擇ai。第三種,如果bi在前面沒有被選過,可以選擇bi。求最多可以選擇多少種不同的數字。對數字進行...

2020牛客暑期多校訓練營(第八場)

題目鏈結 a all star game 題意 有n個運動員與m個球迷,現給你n個運動員各自的球迷編號,現在問你若要m名球迷都看比賽,至少需要多少名運動員上場?滿足球迷看比賽的條件 1 該球迷喜歡的運動員有上場 2 球迷i與球迷j都有相同的喜歡球員,則球迷j喜歡運動員k,則球迷i也喜歡運動員k 然後...