很顯然,每個客人都必須從第一道菜開始連續吃,那麼第一道菜的數目就是最大招待客人的數目。
之後就是如何求最大利潤。
由於每個人都必須連續吃菜,那麼後面的菜即使比前面的菜數量多也沒有意義。
我們可以直接預處理,將後面多的菜直接定義為等於前面的菜,形成乙個遞減序列
很顯然,最大利潤就是每一步都貪心地找最大字首和。
使用結構體排序,對每個字首和的數目(也就是結尾菜的數目)進行記錄,最後選擇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 然後...