【记录】AT_abc375模拟赛

实在是阴得没边的一场,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;
}