CF1458C Latin Square

CF1458C Latin Square

题目来源:Codeforces, Codeforces Round #691 (Div. 1), CF#691, CF1458C Latin Square

题目链接

本题题解

发现 ( exttt{RLDU})( exttt{IC}) 是完全不同的两类操作,将它们同时维护很困难。

本题的突破口是:初始时的每个格子,最终都会恰好对应答案里的一个格子。于是我们拆开来考虑每个格子对答案的“贡献”。

把一个格子看成三元组 ((i,j,a_{i,j})),考虑一次操作会对这个三元组产生什么样的影响:

  • ( exttt{R})((x, y, z) o (x,y + 1, z))。注意,这里的加法是在 (mod n) 意义下的,下同。
  • ( exttt{L})((x, y, z) o (x, y - 1, z))。注意,这里的减法是在 (mod n) 意义下的,下同。
  • ( exttt{D})((x, y, z) o (x + 1, y, z))
  • ( exttt{U})((x, y, z) o (x - 1, y, z))
  • ( exttt{I})((x, y, z) o (x, z, y))。即交换 2, 3 两项。
  • ( exttt{C})((x, y, z) o (z, y, x))。即交换 1, 3 两项。

发现转化后,这 (6) 种对三元组进行的操作,是“可合并”的。

具体地,我们遍历要进行的 (m) 个操作,就能预处理出:依次进行这些操作后,任意一个初始三元组会产生什么变化。

然后枚举每个格子,将预处理出的变化作用于这个格子上,就能知道这个格子最终对答案的贡献是什么。

时间复杂度 (mathcal{O}(m + n^2))

参考代码

建议使用快速输入、输出,详见本博客公告。

// problem: CF1458C
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define mk make_pair
#define lob lower_bound
#define upb upper_bound
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

template<typename T> inline void ckmax(T& x, T y) { x = (y > x ? y : x); }
template<typename T> inline void ckmin(T& x, T y) { x = (y < x ? y : x); }

const int MAXN = 1000;
const int MAXM = 1e5;

int n, m;
int a[MAXN + 5][MAXN + 5];
char s[MAXM + 5];

int ord[4], val[4], res[4];
int ans[MAXN + 5][MAXN + 5];

void solve_case() {
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			cin >> a[i][j];
		}
	}
	cin >> (s + 1);
	
	ord[1] = 1;
	ord[2] = 2;
	ord[3] = 3; // 三元组 (i, j, a[i][j])
	val[1] = val[2] = val[3] = 0;
	for (int i = 1; i <= m; ++i) {
		if (s[i] == 'R') {
			val[ord[2]]++;
		} else if (s[i] == 'L') {
			val[ord[2]]--;
		} else if (s[i] == 'D') {
			val[ord[1]]++;
		} else if (s[i] == 'U') {
			val[ord[1]]--;
		} else if (s[i] == 'I') {
			swap(ord[2], ord[3]);
		} else if (s[i] == 'C') {
			swap(ord[1], ord[3]);
		} else {
			assert(0);
		}
	}
	// cerr << "changes in val: " << val[1] << " " << val[2] << " " << val[3] << endl;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			// (i, j, a[i][j])
			
			for (int k = 1; k <= 3; ++k) {
				if (ord[k] == 1) {
					res[k] = i + val[1];
				} else if (ord[k] == 2) {
					res[k] = j + val[2];
				} else if (ord[k] == 3) {
					res[k] = a[i][j] + val[3];
				}
				
				res[k] = (res[k] % n + n) % n;
				if (res[k] == 0)
					res[k] = n;
			}
			
			// cerr << "** " << res[1] << " " << res[2] << " " << res[3] << endl;
			ans[res[1]][res[2]] = res[3];
		}
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			cout << ans[i][j] << " 
"[j == n];
		}
	}
}
int main() {
	int T; cin >> T; while (T--) {
		solve_case();
	}
	return 0;
}
原文地址:https://www.cnblogs.com/dysyn1314/p/14163636.html