Codeforces Round #799 (Div. 4) A-H
Codeforces Round #799 (Div. 4)
https://codeforces.com/contest/1692
我心痛死了。。。昨天卡在E题,然后没往下做,结果今天补题的时候发现G题贼简单TAT我哭死!!
A. Marathon
统计b c d 中有多少个比 a 大的
#include <bits/stdc++.h>
using namespace std;
void solve () {
int a, b, c, d;
int cnt = 0;
cin >> a >> b >> c >> d;
if (b > a)
cnt ++;
if (c > a)
cnt ++;
if (d > a)
cnt ++;
cout << cnt << endl;
}
int main () {
int t;
cin >> t;
while (t --)
solve ();
}
B. All Distinct
每次删掉两个数字,留下的数列当中不能有相同的数字,求留下的最大长度。
实现:统计有多少种数字,记为m,然后看总数n-m是否为偶数;是的话m就是答案,否则要多删除一个
#include <bits/stdc++.h>
using namespace std;
void solve () {
int n;
cin >> n;
vector <int> v (n + 1);
for (int i = 0; i < n; i ++)
cin >> v[i];
sort (v.begin (), v.end ());
// for (auto i : v)
// cout << i << ' ';
// cout << endl;
v.erase (unique (v.begin(), v.end ()), v.end());
// for (auto i : v)
// cout << i << ' ';
// cout << endl;
int m = v.size () - 1;
if ((n - m) & 1)
cout << max (0, m - 1) << endl;
else
cout << m << endl;
}
int main () {
int t;
cin >> t;
while (t --)
solve ();
}
C. Where's the Bishop?
据观察不难发现,只需找出
的形状即可
#include <bits/stdc++.h>
using namespace std;
void solve () {
char a[9][9];
for (int i = 1; i <= 8; i ++)
for (int j = 1; j <= 8; j ++)
cin >> a[i][j];
for (int i = 1; i <= 7; i ++)
for (int j = 1; j <= 7; j ++)
if (a[i][j] == '#' && a[i-1][j-1] == '#' && a[i-1][j+1] == '#' && a[i+1][j-1] == '#' && a[i+1][j+1] == '#') {
cout << i << ' ' << j << endl;
break;
}
}
int main () {
int t;
cin >> t;
while (t --)
solve ();
}
D. The Clock
非常像学校OJ题的一道模拟
注意分到了60会进位!!这里调了半天xs
#include <bits/stdc++.h>
using namespace std;
bool check (int x, int y) {
string s1, s2;
if (x < 10) s1 = '0' + to_string (x);
else s1 = to_string (x);
if (y < 10) s2 = '0' + to_string (y);
else s2 = to_string (y);
reverse (s2.begin (), s2.end());
if (s1 == s2)
return true;
return false;
}
void solve () {
string s;
int x;
cin >> s >> x;
int dh = x / 60, dm = x % 60;
int sh = (s[0] - '0') * 10 + (s[1] - '0');
int sm = (s[3] - '0') * 10 + (s[4] - '0');
int cnt = check (sh, sm) ? 1 : 0;
if (x == 1440) {
cout << cnt << endl;
return ;
}
int hh = sh, mm = sm;
do {
//cout << hh << ' ' << mm << endl;
hh = hh + dh, mm = dm + mm;
if (mm >= 60) hh += (mm / 60), mm %= 60;
hh %= 24;
if (hh == sh && mm == sm)
break;
if (check (hh, mm)) cnt ++;// cout << hh << ' ' << mm << endl;;
} while (1);
cout << cnt << endl;
}
int main () {
int t;
cin >> t;
while (t --)
solve ();
}
//回文
E. Binary Deque
我处理的很复杂。。其实就是简单的扫一遍双指针记录最小答案(因为div4都是很暴力的)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
int a[N];
void solve () {
int n, s, sum = 0;
cin >> n >> s;
for (int i = 1; i <= n; i ++)
cin >> a[i], sum += a[i];
if (sum == s) {
cout << 0 << endl;
}
else if (sum < s) {
cout << -1 << endl;
}
else {
int ans = 2e5 + 5, sum = 0;
for (int i = 1, j = 1; i < n; i ++) {
while (j <= n && sum + a[j] <= s) {
sum += a[j ++];
}
ans = min (ans, i + n - j);
sum -= a[i]; //有点类似回溯的思想
}
cout << ans << endl;
}
}
int main () {
int t;
cin >> t;
while (t --)
solve ();
}
//统计边缘的1
//统计1的代价
//双指针
//我不会写双指针。。泪目
F. 3SUM
直接鼓励大胆的暴力
出现三次以上的不考虑
#include <bits/stdc++.h>
using namespace std;
void solve () {
vector <int> v;
int n;
cin >> n;
int cnt[10] = {};
for (int i = 0; i < n; i ++) {
int x;
cin >> x;
x %= 10;
if (cnt[x] < 3) {
v.push_back (x);
cnt[x] ++;
}
}
sort (v.begin (), v.end ());
n = v.size ();
// for (auto i : v)
// cout << i << ' ';
// cout << endl;
for (int i = 0; i < n; i ++)
for (int j = i + 1; j < n; j ++)
for (int k = j + 1; k < n; k ++)
if ((v[i] + v[j] + v[k]) % 10 == 3) {
cout << "YES\n";
return ;
}
cout << "NO\n";
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//暴力枚举所有选取三个数的可能
//稍微优化:出现次数超过三次的就不管
G. 2^Sort
就看 区间内 每一个两倍的后一项是否大于前一项
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int a[N];
void solve () {
int n, k, cnt = 0;
cin >> n >> k;
for (int i = 1; i <= n; i ++)
cin >> a[i];
int len = 0;
for (int i = n; i > 1; i --) {
if (a[i] * 2 > a[i - 1])
len ++;
else
len = 0;
if (len == k)
cnt ++, len --;
}
cout << cnt << endl;
}
signed main () {
int t;;
cin >> t;
while (t --) {
solve ();
}
}
//区间内 每一个两倍的后一项是否大于前一项
//倒着看
H. Gambling
求最大子段和。
因为我不会,所以参考了jls的代码。苯人看了好久才懂的,所以放上一些潦草的笔记辅助像我一样的菜鸡来理解:
我觉得自己手动模拟一遍就很好理解了
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve () {
int n;
cin >> n;
map<int, vector <int>> p; //值 下标
vector<int> x(n);
for (int i = 0; i < n; i ++) {
cin >> x[i];
p[x[i]].push_back (i); //记录同一数字的下标
}
int a = x[0], l = 0, r = 1, ans = 1;
for (auto i : p) {
auto q = i.second;//下标列表
int val = 0, st = q[0]; //区间贡献 起点
for (int j = 0; j < q.size (); j ++) {
int ed = q[j];
int cur = j - (ed - j);//统计该区间的贡献值
if (cur < val) val = cur, st = ed; //该行的作用在于,如果出现负值就说明前面段的选取不是最优的,要舍弃,跳过去
int res = cur + 1 - val;
//记录答案
if (res > ans) {
ans = res;
a = i.first, l = st, r = ed + 1;
}
}
}
cout << a << ' ' << l + 1 << ' ' << r << endl;
}
signed main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}