Codeforces Round #792 (Div. 1 + Div. 2) A—D
Codeforces Round #792 (Div. 1 + Div. 2)
https://codeforces.com/contest/1684
A. Digit Minimization
特判两位数的情况(答案只能为个位数),其余的只需要找出最小的那个数字即可
#include <bits/stdc++.h>
using namespace std;
int main () {
int t;
cin >> t;
while (t --) {
int n;
cin >> n;
if (n < 100) {
cout << n % 10 << endl;
continue;
}
//min
int x = 9;
while (n) {
x = min (x, n % 10);
n /= 10;
}
cout << x << endl;
}
}
B. Z mod X = C
没做出来,贴上官方题解:
故令\(x = a + b + c, y = b + c, z = c\)即可
真没想到要这么构造,只能说多练吧emm
#include <bits/stdc++.h>
using namespace std;
int main () {
int t;
cin >> t;
while (t --) {
long long a, b, c;
cin >> a >> b >> c;
cout << a + b + c << ' ' << b + c << ' ' << c << endl;
}
}
//这构造实在是想不到
C. Column Swapping
一开始读错题目了,看成列的非降(英语太差emmm)
后来的想法是求每行的逆序对,然后如果某一行的逆序对数量大于1就直接不可能。如果等于1就看别的行的逆序对是不是也在这个位置上。注意的是再判断一下原本就有序的其他行,在交换后合不合理。(判断方法:比较这两处的大小,\(a_x \geq a_y\)就合理。
(但是我没整出来,可能是代码能力太弱了)
后来又换了一种做法,就是直接交换每两行的任意逆序位置(即从两头开始找,找到就交换),但是也做错了。。
错误:分case没问题,合在一起就输出全为1 1
出错的点在于,每一次开新cases的时候没有初始化,而且这么找也不太对(没法完全有序)
错误代码:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
vector <int> a[N];
int cnt;
int n, m;
struct Node {
int hang, x, y;
}ans [N];
void find (int x) {
for (int i = 1, j = m; i < j; i ++, j --) {
if (a[x][i] > a[x][j]) {
ans[cnt ++] = {x, i, j};
break;
}
}
}
void test () {
for (int i = 0; i < cnt; i ++)
cout << i << ": " << ans[i].hang << ' ' << ans[i].x << ' ' << ans[i].y << endl;
}
void solve () {
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
a[i].push_back (0);
for (int j = 1; j <= m; j ++) {
int t;
cin >> t;
a[i].push_back (t);
}
find (i);
}
if (cnt == 0) {
cout << 1 << ' ' << 1 << endl;
return ;
}
//test ();
if (cnt == 1) {
for (int i = 1; i <= n; i ++) {
if (i == ans[0].hang)
continue;
int xx = ans[0].x, yy = ans[0].y;
if (a[i][xx] < a[i][yy]) {
cout << -1 << endl;
return ;
}
else {
cout << xx << ' ' << yy << endl;
return ;
}
}
}
bool flag = true;
for (int i = 1; i < cnt; i ++) {
if (ans[i].x != ans[i - 1].x || ans[i].y != ans[i - 1].y) {
flag = false;
break;
}
}
if (flag)
cout << ans[0].x << ' ' << ans[0].y << endl;
else
cout << -1 << endl;
}
int main () {
int t;
cin >> t;
while (t --) {
cnt = 0;
solve ();
}
}
//只交换两个<=1次,变成列非减
//求逆序对数量
//整列交换
//找到就交换
正确代码
就该用is_sorted 按行来判断
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
int cnt;
int n, m;
void solve () {
cin >> n >> m;
vector <vector <int>> a(n, vector<int>(m)), b(n, vector<int>(m));
for (int i = 0; i < n; i ++)
for (int j = 0; j < m; j ++) {
cin >> a[i][j], b[i][j] = a[i][j];
//a[i].push_back (t), b[i].push_back (t);
}
for (int i = 0; i < n; i ++)
sort (b[i].begin (), b[i].end());
//锁定要交换的两列
int x = -1, y = -1;
bool find = false;
for (int i = 0; i < n; i ++) {
for (int j = 0; j < m; j ++) {
if (a[i][j] != b[i][j]) {
if (x == -1) x = j, find = true;
else if (y == -1) y = j; //x更新完了,才更新y
}
}
if (find) break;
}
if (x == -1) //没更新
x = y = 0;
for (int i = 0; i < n; i ++)
swap (a[i][x], a[i][y]);
bool flag = true;
for (int i = 0; i < n; i ++)
if (!is_sorted (a[i].begin (), a[i].end ())) {
flag = false;
break;
}
if (flag) cout << x + 1 << ' ' << y + 1 << endl; //偏移
else cout << -1 << endl;
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//每一行都排一下序,然后看看符合不
D. Traps
贪心,摆个大佬的证明:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
int n, k;
ll a[N];
bool skip[N]; //是否需要跳过
pii b[N]; //a_i+i(用于排序),second记录下标
void solve () {
memset (skip, false, sizeof skip);
ll ans = 0;
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i], b[i].first = a[i] + i, b[i].second = i;
if (n == k) {
cout << 0 << endl;
return ;
}
sort (b + 1, b + n + 1, greater <pii> ());
for (int i = 1; i <= k; i ++)
skip[b[i].second] = true; //前k大的需要skip
ll d = 0; //叠加量
for (int i = 1; i <= n; i ++) {
if (skip[i])
d ++;
else
ans += a[i] + d;
}
cout << ans << endl;
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//每个点的价值相当于a_i+i,然后排序,去掉前k个
//注意伤害可叠加
//有点像能量石