Educational Codeforces Round 90 (Rated for Div. 2)A、B、C、D
题目
A题意:两家商店卖相同产品但售卖方式不同,第一家零售一件一件卖价格为a元,第二家b(b>=2)件一起卖(如果要买得话就得向上取整)c元,问在第一家商店买多少会比第二家便宜,
在第二家商店买多少会比第一家便宜。答案至少买一件否则输出-1.
解法:首先考虑第一家商店买:如果a>=c,无论如何买都无法比第二家买便宜,因为c是至少两件商品得价格,a是一件商品价格。如果a<c,那就买一件一定在第二家便宜。
考虑第二家商店买:如果在第一家店买b件比在第二家贵,那就买b件,否则不可能比第一家便宜。
void solve(){
int a , b , c ;
cin >> a >> b >> c;
if(a < c){//考虑第一商家
cout << 1 << " " ;
}else{
cout << -1 << " " ;
}
if(a*b>c){//考虑第二商家且第一商家贵
cout << b << endl;
}else{//第一商家便宜
cout << -1 << endl;
}
}
B题意:给出一个01字符串,操作:选择删除任意两个相邻且不同得字符,alice和bob轮流操作,不能操作一方为输方。问Alice是否赢,能输出'DA',不能'NET'.
char s[maxn];
void solve(){
scanf("%s" , s+1);
int a = 0 , b = 0;
rep(i , 1 , strlen(s+1)){
if(s[i] == '0')
a++;
else{
b++;
}
}
int ans = min(a , b);
if(ans%2==1){
cout << "DA" << endl;
}else{
cout << "NET" << endl;
}
}
C题意:给出一段伪代码计算代码中得res值。
res = 0
for init = 0 to inf
cur = init
ok = true
for i = 1 to |s|
res = res + 1
if s[i] == '+'
cur = cur + 1
else
cur = cur - 1
if cur < 0
ok = false
break
if ok
break
解法:前缀记录信息可以不需要外层循环 , 外层循环结束时内层循环一定被完整遍历没有被break,所以最后加上字符串长度。
const int maxn = 1e6+9;
char s[maxn];
void solve(){
scanf("%s" , s+1);
int n = strlen(s+1);
int res = 0 , cur = 0 , ans = 0 , init = 0 ;
rep(i , 1 , n){
if(s[i] == '-'){
cur++;
}else{
cur--;
}
if(cur > init){
ans += i ;
init = cur ;
}
}
cout << ans+n << endl;
}
D题意:给出一个数组a下标从0开始,可以进行至多一次操作:对其子数组进行一次翻转。问偶数下标得最大和为多少。
解法:翻转某一偶数长区间该区间翻转贡献最大。如果直接枚举偶数区间\(O(n^2)\)肯定是不行的,可以进行两次dp求最大连续和时间复杂度为O(n)。
const int maxn = 2e5+9;
int a[maxn];
void solve(){
int n ;
cin >> n;
int sum = 0;
rep(i , 0 , n-1){
cin >> a[i];
if(i%2==0)
sum += a[i];
}
int i = 1 , ma = 0 , ans = 0;
while(i+1 < n){//从第二个元素开始
ans += a[i] - a[i+1];
ma = max(ma , ans);//取可以贡献最大得区间翻转
if(ans < 0) ans = 0;//如果前面和是负得就截断
i+=2;
}
i = 0 , ans = 0 ;
while(i+1 < n){
ans += a[i+1] - a[i];
ma = max(ma , ans);
if(ans < 0) ans = 0;
i += 2 ;
}
cout << sum + ma << endl;
}