实在是阴得没边的一场,a 4 道还需更加努力。
机房两位巨佬太强了。一位一小时 a 6道,一位学一年吊打我三年。
AT_abc375_c ABC375C Spiral Rotation - 洛谷 (luogu.com.cn)
我能说这 c 是我做过最难的吗。
由于我的英语需要加强,没有一眼看出 Spiral Rotation 是"螺旋旋转"。
然后十分钟才发现 (x,y) 和 (y, n - x + 1) 是绝对同时满足条件的。
接着往替换组群想,总共用时 40 分钟。。
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 3010;
char s[N][N];
char t[N][N];
bool v[N][N];
int main () {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> (s[i] + 1);
}
memset(v, 0, sizeof(v));
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) if (v[i][j] == 0) {
int tt = min(min(n - i + 1, n - j + 1), min(i, j));
tt -= 1;
tt %= 4;
for (int k = 0; k <= tt; k ++) {
if (k & 1) {
s[j][n + 1 - i] = t[i][j];
s[n + 1 - i][n + 1 - j] = t[j][n + 1 - i];
s[n + 1 - j][i] = t[n + 1 - i][n + 1 - j];
s[i][j] = t[n + 1 - j][i];
}
else {
t[j][n + 1 - i] = s[i][j];
t[n + 1 - i][n + 1 - j] = s[j][n + 1 - i];
t[n + 1 - j][i] = s[n + 1 - i][n + 1 - j];
t[i][j] = s[n + 1 - j][i];
}
}
if (tt & 1) {
t[j][n + 1 - i] = s[j][n + 1 - i];
t[n + 1 - i][n + 1 - j] = s[n + 1 - i][n + 1 - j];
t[n + 1 - j][i] = s[n + 1 - j][i];
t[i][j] = s[i][j];
}
v[i][j] = v[j][n + 1 - i] = v[n + 1 - i][n + 1 - j] = v[n + 1 - j][i] = 1;
}
}
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
cout << t[i][j];
}
cout << "\n";
}
return 0;
}
AT_abc375_d ABC375D ABA - 洛谷 (luogu.com.cn)
若只题,没话说。
AT_abc375_e ABC375E 3 Team Division - 洛谷 (luogu.com.cn)
太幽默了知道吗,做的时候没往 dp 想。
对我个人来说是需要打破思维定式想的,比起"均衡"三个组的人数。
更应该看作三个存放物品的背包,这样就会好做很多。
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 505;
int dp[2][N][N];
int s[110], a[110], b[110];
void work() {
int n;
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
cin >> b[i];
}
s[0] = 0;
for (int i = 1; i <= n; i ++) {
s[i] = s[i - 1] + b[i];
}
if (s[n] % 3 != 0) {
cout << "-1\n";
return ;
}
memset(dp, 0x3f, sizeof(dp));
int inf = dp[0][0][0];
dp[0][0][0] = 0;
int last = 0;
for (int i = 1; i <= n; i ++) {
memset(dp[last ^ 1], 0x3f, sizeof(dp[last ^ 1]));
for (int j = 0; j <= 500; j ++) {
for (int k = 0; k <= 500; k ++) {
if (j >= b[i]) {
dp[last ^ 1][j][k] = min(dp[last ^ 1][j][k],
dp[last][j - b[i]][k] + (a[i] != 1));
}
if (k >= b[i]) {
dp[last ^ 1][j][k] = min(dp[last ^ 1][j][k],
dp[last][j][k - b[i]] + (a[i] != 2));
}
if (s[i] - j - k >= b[i]) {
dp[last ^ 1][j][k] = min(dp[last ^ 1][j][k],
dp[last][j][k] + (a[i] != 3));
}
}
}
last ^= 1;
}
if (dp[last][s[n] / 3][s[n] / 3] == inf) {
cout << "-1\n";
}
else {
cout << dp[last][s[n] / 3][s[n] / 3] << "\n";
}
}
int main () {
ios::sync_with_stdio(false);
cin.tie(0);
work();
return 0;
}
AT_abc375_f ABC375F Road Blocked - 洛谷 (luogu.com.cn)
27,000,000 是我不敢打了,其实完全能过的吧。
加边时用下 floyd。
cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 310;
const int M = N * N;
const int T = 2e5 + 10;
struct no {
int x, y;
LL c;
int id;
} a[M];
struct qu {
int opt;
int i;
int x, y;
LL ans;
} q[T];
LL f[N][N];
int n;
int main () {
ios::sync_with_stdio(false);
cin.tie(0);
int m, QQ;
cin >> n >> m >> QQ;
memset(f, 0x3f, sizeof(f));
for (int i = 1; i <= m; i ++) {
cin >> a[i].x >> a[i].y >> a[i].c;
a[i].id = 1;
}
for (int i = 1; i <= QQ; i ++) {
cin >> q[i].opt;
if (q[i].opt == 1) {
cin >> q[i].i;
a[q[i].i].id = 0;
}
else {
cin >> q[i].x >> q[i].y;
}
}
for (int i = 1; i <= m; i ++) if (a[i].id == 1) {
f[a[i].x][a[i].y] = f[a[i].y][a[i].x] = a[i].c;
}
for (int i = 1; i <= n; i ++) {
f[i][i] = 0;
}
for (int k = 1; k <= n; k ++) {
for (int i = 1; i <= n; i ++) if (i != k) {
for (int j = 1; j <= n; j ++) if (j != i && j != k) {
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}
}
}
for (int i = QQ; i >= 1; i --) {
if (q[i].opt == 2) {
if (f[q[i].x][q[i].y] == f[0][0]) {
q[i].ans = -1;
}
else {
q[i].ans = f[q[i].x][q[i].y];
}
}
else {
int x = a[q[i].i].x, y = a[q[i].i].y;
LL c = a[q[i].i].c;
f[x][y] = f[y][x] = min(f[x][y], c);
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) if (i != j) {
f[i][j] = min(f[i][j], f[i][x] + f[y][j] + c);
f[i][j] = min(f[i][j], f[i][y] + f[x][j] + c);
}
}
}
}
for (int i = 1; i <= QQ; i ++) if (q[i].opt == 2) {
cout << q[i].ans << "\n";
}
return 0;
}
AT_abc375_g ABC375G Road Blocked 2 - 洛谷 (luogu.com.cn)
只有一条边同时在全部最短路方案上时,这条边去掉最短路长度才会变。
分成两块,一个 d 是从 1 到 n,另一个 d 从 n 到 1。
如果强制选当前边,就要保证:

满足这两个条件其中之一,就代表当前边是必须在最短路上的。
cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
const LL P = 998244353;
struct node {
int x;
LL c;
};
vector<node> G[N];
struct nnode {
int x, y;
LL c;
} a[N];
LL d[2][N];
LL pos[2][N];
bool operator<(node na, node nb) {
return na.c > nb.c;
}
void get_d(int st, int ed, int id) {
memset(d[id], 0x3f, sizeof(d[id]));
memset(pos[id], 0, sizeof(pos[id]));
d[id][st] = 0; pos[id][st] = 1;
priority_queue<node> Q;
Q.push({st, 0});
while (!Q.empty()) {
node no = Q.top(); Q.pop();
for (node i : G[no.x]) {
if (d[id][i.x] >= no.c + i.c) {
if (d[id][i.x] == no.c + i.c) {
pos[id][i.x] = (pos[id][i.x] + pos[id][no.x]) % P;
}
else {
pos[id][i.x] = pos[id][no.x];
d[id][i.x] = no.c + i.c;
Q.push({i.x, d[id][i.x]});
}
}
}
}
}
int main () {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i ++) {
cin >> a[i].x >> a[i].y >> a[i].c;
G[a[i].x].push_back({a[i].y, a[i].c});
G[a[i].y].push_back({a[i].x, a[i].c});
}
get_d(1, n, 0);
get_d(n, 1, 1);
for (int i = 1; i <= m; i ++) {
if (d[0][a[i].x] + d[1][a[i].y] + a[i].c == d[0][n]
&& pos[0][a[i].x] * pos[1][a[i].y] % P == pos[0][n]) {
cout << "Yes\n";
}
else if (d[1][a[i].x] + d[0][a[i].y] + a[i].c == d[0][n]
&& pos[1][a[i].x] * pos[0][a[i].y] % P == pos[0][n]) {
cout << "Yes\n";
}
else {
cout << "No\n";
}
}
return 0;
}