这场比赛水了4个题。 部分题解如下:
A. Launch of Collider
A题:我们每次遇到一个L, 就找到上一个R,他们肯定是比较近的, 这些中最近的就是最近的辣。
细节参见代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 2e5 + 10;
int n,m,l[maxn],r[maxn],pos[maxn];
char s[maxn];
int main() {
scanf("%d%s", &n, s+1);
for(int i = 1; i <= n; i++) {
scanf("%d", &pos[i]);
}
memset(l, -1, sizeof(l));
int cnt = 0, ans = INF;
for(int i = 1; i <= n; i++) {
if(s[i] == 'L') {
if(cnt > 0) {
int cur = (pos[i] - l[cnt]) / 2;
ans = min(ans, cur);
}
}
else {
l[++cnt] = pos[i];
}
}
if(ans == INF) printf("-1\n");
else printf("%d\n", ans);
return 0;
}
B. One Bomb
B题:统计每一行和每一列*的个数, 然后n*m暴力枚举放炸弹
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 1e3 + 10;
int n,m,r[maxn],c[maxn];
char s[maxn][maxn];
int main() {
// ios::sync_with_stdio(false);
scanf("%d%d", &n, &m);
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%s", s[i]+1);
for(int j = 1; j <= m; j++) {
if(s[i][j] == '*') ++sum, r[i]++;
}
}
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
if(s[j][i] == '*') {
c[i]++;
}
}
}
bool ok = false;
int rr, cc;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(s[i][j] == '.') {
int cur = r[i] + c[j];
if(cur == sum) { rr = i; cc = j; ok = true; break; }
}
else {
int cur = r[i]+c[j]-1;
if(cur == sum) { rr = i; cc = j; ok = true; break; }
}
}
if(ok) break;
}
if(ok) {
printf("YES\n");
printf("%d %d\n", rr, cc);
}
else printf("NO\n");
return 0;
}
<span style="color: rgb(34, 34, 34); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 21px; line-height: 21px; text-align: center;">C. Vacations</span>
C题:水DP, 用d[i][j]表示第i天在干什么的最优解
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 1e2 + 10;
int n,m,jian[maxn], bi[maxn], a[maxn], d[maxn][5];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if(a[i] == 0) ;
else if(a[i] == 1) bi[i] = 1;
else if(a[i] == 2) jian[i] = 1;
else jian[i] = 1, bi[i] = 1;
}
for(int i = 1; i <= n; i++) {
for(int j = 0; j < 3; j++) {
d[i][j] = INF;
if(i == 1) {
if(j == 0) d[i][j] = 1;
else if(j == 1) {
if(jian[1]) d[i][j] = 0;
else d[i][j] = INF;
}
else {
if(bi[1]) d[i][j] = 0;
else d[i][j] = INF;
}
continue;
}
if(j == 0) {
d[i][j] = min(d[i][j], d[i-1][0]+1);
d[i][j] = min(d[i][j], d[i-1][1]+1);
d[i][j] = min(d[i][j], d[i-1][2]+1);
}
else if(j == 1) {
if(jian[i]) {
d[i][j] = min(d[i][j], d[i-1][0]);
d[i][j] = min(d[i][j], d[i-1][2]);
}
else d[i][j] = INF;
}
else {
if(bi[i]) {
d[i][j] = min(d[i][j], d[i-1][0]);
d[i][j] = min(d[i][j], d[i-1][1]);
}
else d[i][j] = INF;
}
}
}
int ans = INF;
for(int i = 0; i < 3; i++) {
ans = min(ans, d[n][i]);
}
printf("%d\n", ans);
return 0;
}
D题:将一个非法树用最少的次数修改成合法的。 用并查集判圈就行了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 2e5 + 10;
int n,m,a[maxn],p[maxn];
int _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
p[i] = i;
}
bool ok = false;
int root = -1, ans = 0;
for(int i = 1; i <= n; i++) {
if(a[i] == i) {
ok = true;
root = i;
break;
}
}
for(int i = 1; i <= n; i++) {
int fa = a[i];
int u = i;
if(!ok) {
int x = _find(fa);
int y = _find(u);
if(x != y) {
p[x] = y;
}
else {
a[i] = i;
root = i;
++ans;
ok = true;
}
continue;
}
if(u == fa) {
if(u == root) ;
else {
a[i] = root;
++ans;
}
}
else {
int x = _find(fa);
int y = _find(u);
if(x != y) {
p[x] = y;
}
else {
a[i] = root;
++ans;
}
}
}
printf("%d\n", ans);
for(int i = 1; i <= n; i++) printf("%d%c", a[i], i == n ? '\n' : ' ');
return 0;
}