A - Maximum Cake Tastiness
题意
给定一个长度为n的蛋糕序列,定义美味值为其中两个相邻的蛋糕美味值的和的最大值可以进行一次子串翻转操作,问最后最大的美味值是多少
题解
我们很容易发现,最大值让两个最大的在一起就行了,翻转子串也很容易得到最大值在一起,所以直接输出两个最大值相加就行了
Code
int n;
int a[N];
void solve(){
cin >> n;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
sort(a + 1, a + 1 + n);
cout << a[n] + a[n - 1] << endl;
}
B - Prefix Removals
题意
按照规则删除前缀,直到不能删除为止,输出剩下的字符
- 设x是s的最长前缀的长度,该前缀作为相邻子串出现在s的其他地方(另一种情况也可能与前缀相交)。 如果x = 0,停止。 否则,删除s的前x个字符,重复执行
题解
其实我们发现,如果某一个前缀在后面出现过,那么这个前缀的每一个字符也可以作为一个前缀来删除,所以我们只需要判断每一个字符是否在后面多次出现过就可以了
Code
string s;
void solve(){
cin >> s;
map<char, int> m;
for(auto i : s){
m[i]++;
}
for (int i = 0; i < s.size(); i++){
if(m[s[i]] > 1)
m[s[i]]--;
else{
cout << s.substr(i, s.size() - i) << endl;
return;
}
}
}
C - Alice and the Cake
题意
给定一个最终切分的蛋糕序列,每一次切割可以将一个大小为w的蛋糕切分为 ⌊ w 2 ⌋ \lfloor\frac{w}{2}\rfloor ⌊2w⌋和 ⌈ w 2 ⌉ \lceil\frac{w}{2}\rceil ⌈2w⌉两种重量的
问当前给定的蛋糕序列,是否为一个合法的蛋糕切分来的
题解
这个题真的学到到了
很容易我们想到,我们dfs看看是否能用这些数据来进行整合为合法的蛋糕
但是我们发现这并不好做
这个也可以正难则反!
首先我们当然知道,如果这个蛋糕是合法的,那么一定是由 ∑ \sum ∑重量来分配的
那么我们只需要看看,我们当前的sum能否用现有的这些数凑出来就行了
Code
int T;
int n;
int a[N];
map<ll, int> m;
int ok;
void dfs(ll x){
if(ok) // 不合法就没有必要再往下了
return;
if(m[x]){ // 是否有这个数,有就用一次
m[x]--;
n--;
return;
}
else{
if(x == 1){ // 如果当前切出来的蛋糕出现重量是1的,这个蛋糕就没法往下切了,就说明凑不出来这样的答案
ok = 1;
return;
}
else{
ll a = x / 2; // 上下取整
ll b = (x + 1) / 2;
dfs(a), dfs(b);
}
}
}
void solve(){
m.clear();
ok = 0;
cin >> n;
ll summ = 0;
for (int i = 1; i <= n; i++){
cin >> a[i];
m[a[i]]++;
summ += a[i];
}
if(n == 1){
cout << "YES" << endl;
}
else{
dfs(summ);
if(!ok && !n){ // 是否合法,并且全部都用
cout << "YES" << endl;
}
else
cout << "NO" << endl;
}
}