Educational Codeforces Round 184 (Div. 2)
A. Alice and Bob
根据题目要求,Bob要想得分最大化就是要使Bob能够得分的球尽可能得多。
通过 lower_bound 函数和 upper_bound(这是因为题目中说平局也就是数组中的元素与a一样大是使Alice得分,我们要避免与a相同) 函数分别得到 比 a 小和比 a 的元素的数量,紧接着就是分类讨论,如果 left 比 right 要多,则让b = a - 1,则左边的数更接近与 b ,否则让 b=a + 1.
void solve(){ int n, a; cin >> n >> a; vector<int> v(n + 1); for(int i = 1; i <= n; ++i) cin >> v[i]; int left =lower_bound(v.begin() + 1, v.end(), a) - v.begin(); int right = upper_bound(v.begin() + 1, v.end(), a) - v.begin(); if(left - 1 >= (n - right + 1)){ cout << a - 1 << endl; }else{ cout << a + 1 << endl; } return ; }
B. Drifting Away
多花点时间枚举一些情况就行了。"**"、"*<"、">*"、"><" 这四种情况可以无限航行,只要字符串中出现这样的组合输出-1就行。
排除无限航行的情况后就是计算最长的航行时间了,"<<<<<*>>"、"<<<<<>>>>",要航行到岸边,要么字符串左边存在连续的"<",要么字符串右侧出现连续的">",那么我们记两个指针left 和 right,一个从左往右记录有多少个"<",一个从右往左记录有多少">"。遍历完成后就可以进行比较了。如果遍历结束后left 和 right 的位置有 "*",那可以从 "*"开始走增加航行时间,分类讨论下就行。
void solve(){ string s; cin >> s; int len = s.length(); for(int i = 0; i < len - 1; ++i){ if(s[i] == '*'){ if(s[i + 1] == '*' || s[i + 1] == '<'){ cout << -1 << endl; return ; } }else if(s[i] == '>'){ if(s[i + 1] == '<' || s[i + 1] == '*'){ cout << -1 << endl; return ; } } } int l = 0, r = len - 1; int cnt0 = 0, cnt1 = 0; while(s[l] == '<' && l < len) { l++; cnt0++; } while(s[r] == '>' && r >= 0){ r--; cnt1++; } if((s[l] == '*' || s[r] == '*') && l < len && r >= 0){ cout << max(cnt0, cnt1) + 1 << endl; }else{ cout << max(cnt0, cnt1) << endl; } return ; }
C. Range Operation
根据题目可以推出上述等式,其中res表示数组前缀和。只要保证 F(R) - F(L-1) 最大就行,逐个遍历一遍就行,每次尽可能得取 F(L-1) 的最小值就行
void solve(){ int n; cin >> n; vector<int> a(n + 1); int sum = 0; for(int i = 1; i <= n; ++i) { cin >> a[i]; sum += a[i]; } vector<int> res(n + 1, 0); for(int i = 1; i <= n; ++i){ res[i] = res[i - 1] + a[i]; } vector<int> f(n + 1, 0); for(int i = 1; i <= n; ++i){ f[i] = i * i + i - res[i]; } int minn = MAX; int t = 0; for(int i = 0;i <= n; ++i){ minn = min(minn, f[i]); t = max(t, f[i] - minn); } cout << t + sum << endl; return ; }
D1. Removal of a Sequence (Easy Version)
通过题目可以知道每次都会删除第 y 的倍数的数字,求第k个数是什么。那我们这样想,如果经过 x 次删除后正好剩 k 个数,那么这第 k 个数就应该是未经过x次删除的原数的个数。
那么这样就好想了,每次枚举数的数量,经过 x 次删除后判断是否有 k 个数,二分答案。
假设原数的个数为 p ,每次会删除 y 的倍数,那么每次删除就还剩 p -= p - [p / y] 个数,以此为二分的判断依据。
void solve(){ cin >> x >> y >> k; int l = 1, r = 1e12; int ans = -1; while(l <= r){ int mid = l + r >> 1; if(check(mid)){ l = mid + 1; }else{ ans = mid; r = mid - 1; } } cout << ans << endl; }


浙公网安备 33010602011771号