A - Make it Beautiful
题意:给出一个序列a,要求重新排列它,使前\(i - 1\)个数之和不等于\(a_i\)
思路:数据范围很小。用桶存数字,然后由大到小每种数字为一组循环输出即可
赛时没看到数组是有序的,所以直接判断第一个和最后一个是不是一样的即可,如果是则NO,否则翻转第二个到最后一个,一定可以构造成功
void solve() {
int n;
cin >> n;
int cnt[101] = {0};
for (int i = 1; i <= n; i ++) {
cin >> a[i];
cnt[a[i]] ++;
}
int x = n, j = 1;
while (1) {
for (int i = 100; i >= 1; i --) {
if (cnt[i] != 0) {
a[j ++] = i;
cnt[i] --;
x --;
}
}
if (!x) break;
}
int sum = a[1];
bool flag = 1;
for (int i = 2; i <= n; i ++) {
if (sum == a[i]) {
flag = 0;
break;
}else sum += a[i];
}
if (!flag) {
cout << "NO" <<endl;
}
else {
cout << "YES" << endl;
for (int i = 1; i <= n; i ++) cout << a[i] << ' ';
cout << endl;
}
}
\[\]B - Matrix of Differences
题意:给出一个n,要求构造出一个n*n的矩阵,使矩阵相邻数字的绝对值种类最多
思路:首先想出满足条件的序列是什么:n * n, 1, n * n - 1, 2, n * n - 2, 3这种序列是可以满足条件的。再想怎么以矩阵的形式输出,因为要保留连续的关系,故而用蛇形输出矩阵即可
void solve() {
int n;
cin >> n;
int l = 1, r = n * n, ok = 1;
vector<vector<int>> a(n + 1, vector<int> (n + 1));
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
if (ok) {
a[i][j] = l ++;
}else a[i][j] = r --;
ok ^= 1;
}
if (i % 2 == 0) {
reverse(a[i].begin() + 1, a[i].end());
}
}
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
cout << a[i][j] << " \n"[j == n];
}
\[\]C - Yet Another Tournament
题意:有n+1个人,m的时间,每两个人之间都要进行比赛。除开自己以外,其他人都是以序号定为胜负条件,第一个人无胜场,第二个人胜一场……第n个人胜n-1场。而自己与别人的的对战需要消耗时间\(a_i\)才能胜利。问最高排名多少
思路:首先,n个人的排名已经清晰,我们需要找到的就是如何最大限度的花费时间,得到最高名次,也就是打败更多的人。则将a数组从小到大排序,然后用m依次减去能减得,res++。这样获得的res就是最多能打败几个人。而n-res+1则是你的最终名次。此时你的名次是res,第res+1个人也只胜了res场(和你的那场不算),若是剩下的m + b[res] >= a[res+1],也就是我们可以将之前某一场的时间和当前剩下的时间加起来打败第res+1这个人,这样我们胜场数不变,而第res+1这个人的胜场跟我们一样,我们就可以跟res+1一样名次,res++。比如样例1 2 2 4,本来我们最多是第三名,但是如果将剩下的1用上,则我们可以到达第二名。
void solve() {
int n, m;
cin >> n >> m;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++) cin >> a[i];
auto b = a;
sort(b.begin() + 1, b.end());
int res = 0;
for (int i = 1; i <= n; i ++) {
if (m >= b[i]) {
m -= b[i];
res ++;
}else break;
}
if (res != 0 && res != n && m + b[res] >= a[res + 1]) res ++;
cout << n + 1 - res << endl;
}