#1:Absolute Game
思路:
一开始拿到这道题没有什么思路,大概算了算样例,想到一个用前缀和求出绝对值差的方案,结果。。。。
正解:
因为所有人足够聪明,又因为我们已经知道了“A”是先手,所以我们可以枚举A每次选择剩下的那个数 k k k,那么B肯定会剩下一个与 k k k绝对值差最小的数,所以直接枚举,时间复杂度 O ( n 2 ) O(n^2) O(n2)
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 1005;
int n, m, a[MAXN], b[MAXN];
int Abs(int s) {
if(s < 0) return -s;
return s;
}
int main() {
scanf("%d", &n);
for(int i = 1;i <= n; i++) scanf("%d", &a[i]);
for(int i = 1;i <= n; i++) scanf("%d", &b[i]);
int _max = -0x3f3f3f3f;
for(int i = 1;i <= n; i++) {
int _min = 0x3f3f3f3f;
for(int j = 1;j <= n; j++) _min = min(_min , Abs(a[i] - b[j]));
_max = max(_max, _min);
}
printf("%d", _max);
return 0;
}
#2:「Copy and Paste 2」
思路:
一开始想到了一个思路,就是手动模拟,结果发现要打递归,并且递归因为边界问题很难写,果断放弃。赛后发现可以逆推,瞬间想起自己放弃模拟,想打自己一巴掌。。。。
正解:
想到模拟这道题其实就非常简单,首先观察到
k
k
k很小,我们可以枚举k,然后用没次操作去还原k的位置(设操作‘A’,‘B’, ‘C’):
1.如整段操作都在此位置左边,它会把k向后推
(
B
−
A
+
1
)
(B - A + 1)
(B−A+1)个位置,减掉即可。
2.若包含,调到取代k的位置。
3.若在右边无效。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN = 2e5 + 5;
int kk, flag[MAXN], m, n;
char s[MAXN];
string ans;
struct node{
int l, r, c;
node(){}
node(int L, int R, int C) {
l = L;
r = R;
c =C;
}
}a[MAXN];
int main() {
scanf("%d %d", &kk, &m);
scanf("%s", s + 1);
scanf("%d", &n);
for(int i = 1;i <= n; i++) scanf("%d %d %d", &a[i].l, &a[i].r, &a[i].c);
for(int k = 1;k <= kk; k++) {
int now_id = k;
for(int i = n;i >= 1; i--) {
if(a[i].c + 1 <= now_id && now_id <= a[i].c + (a[i].r - a[i].l)) {
int k = now_id - a[i].c - 1;
now_id = a[i].l + k + 1;
}
else if(a[i].c + 1 <= now_id) now_id = now_id - (a[i].r - a[i].l);
}
printf("%c", s[now_id]);
}
return 0;
}