您的位置:首页 > 其它

【解题报告】Codeforces Round #364 (Div. 2)

2016-08-03 02:52 281 查看
题目链接

A. Cards(Codeforces 701A)

思路

因为每个人得到的牌的点数的总和都是一样的,所以可以扫描牌组并把剩下的第一张牌 i 给第一个人,然后为他在剩下的牌中找到点数合适的另一张牌 j (也就是 a[i]+a[j]=2sumn ),这样继续下去,直到所有的牌分完(此时每个人也都分到了 2 张牌)。这样的复杂度是 O(n2) 的。(当然有更好的算法,但是没必要。)

代码

#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 表示有多少行有城堡, C 表示有多少列有城堡, r[i] 表示第 i 行有没有城堡, c[i] 表示第 i 列有没有城堡。假如我们要在 (x,y) 位置新放置一个城堡,先给 res 加上 n+n 。如果 r[x] 为 true 的话,就让 res 减去 n 否则就减去 C (表示去掉 x 这行的重复覆盖部分)。如果 c[y] 为 true 的话就然 res 减去 n 否则就减去 R (表示去掉 y 这行的重复覆盖部分)。最后处理一下 (x,y) 位置被重复加减的情况,输出 res 就行了。

代码

#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;
}


(其它题目略)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息