A. Cards(Codeforces 701A)
思路
因为每个人得到的牌的点数的总和都是一样的,所以可以扫描牌组并把剩下的第一张牌
i
给第一个人,然后为他在剩下的牌中找到点数合适的另一张牌
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
bool vis[maxn];
int n, sum, tmp, cnt, a[maxn], b[maxn], c[maxn];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum += a[i];
}
tmp = 2 * sum / n;
cnt = 1;
for(int i = 1; i <= n; i++) {
if(vis[i] == true) {
continue;
}
b[cnt] = i;
for(int j = i + 1; j <= n; j++) {
if(vis[j] == true) {
continue;
}
if(a[i] + a[j] == tmp) {
vis[j] = true;
c[cnt] = j;
break;
}
}
cnt++;
}
for(int i = 1; i <= n / 2; i++) {
printf("%d %d\n", b[i], c[i]);
}
return 0;
}
B. Cells Not Under Attack(Codeforces 701B)
思路
可以将问题转化为已经放的城堡能够攻击到的方格数
res
。由于每次询问都要瞬间知道
res
,所以要额外维护一些变量:
R
表示有多少行有城堡,
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
bool r[maxn], c[maxn];
ll n, m, x, y, R, C, res;
int main() {
scanf("%I64d%I64d", &n, &m);
while(m--) {
scanf("%I64d%I64d", &x, &y);
res += n + n;
res -= r[x] ? n : C;
R += r[x] == false;
r[x] = true;
res -= c[y] ? n : R;
C += c[y] == false;
c[y] = true;
printf("%I64d ", n * n - res);
}
puts("");
return 0;
}
思路
脑残如我想到上面这个这么麻烦的办法,实际上还有更简便的办法:没被攻击到的格子数 = 没被攻击到的行数 × 没被攻击到的列数。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m, x, y;
set <ll> r, c;
int main() {
cin >> n >> m;
while(m--) {
cin >> x >> y;
r.insert(x);
c.insert(y);
cout << (n - r.size()) * (n - c.size()) << endl;
}
return 0;
}
C. They Are Everywhere(Codeforces 701C)
思路
按照题给的数据量,直接枚举区间然后检查区间是否包含所有神奇宝贝是会超时的。因此我们可以用“尺取法”来解决。用首尾指针来表示目前枚举到的区间,开始先向字符串结尾移动尾指针,移动到将所有神奇宝贝包括在区间内停止(再移动也得不到最优解),然后移动首指针,直到不是所有的神奇宝贝在区间内,再移动尾指针……这样我么就能在 O(n) 的时间内解决问题。另外为了实现算法,我们还需要维护当前区间内每种神奇宝贝有多少个。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
char s[maxn];
int n, head, tail, res, cnt, num;
set<char> ss;
map<char, int> m;
int main() {
scanf("%d%s", &n, s);
for(int i = 0; i < n; i++) {
ss.insert(s[i]);
}
num = ss.size();
res = n;
while(true) {
while(cnt < num && tail < n) {
if(m[s[tail++]]++ == 0) {
cnt++;
}
}
if(cnt < num) {
break;
}
res = min(res, tail - head);
if(--m[s[head++]] == 0) {
cnt--;
}
}
printf("%d\n", res);
return 0;
}
(其它题目略)