题解 [CF1458C] Latin Square

传送门

这一场怎么全是神仙题

发现前四个操作是容易打标记维护的
但是“把每行/列变为其逆排列”这种与每个位置具体值和下标同时有关的东西怎么办呢?

  • 当处理同时涉及位置(下标)和权值的操作时,注意序列/矩阵不必显式的当成序列/矩阵
    而是可以当成二/三元组 \((i, a_i)/(i, j, a_{i, j})\),这样同时涉及下标和权值的操作就会方便一些

回到本题,IC 两种操作分别产生什么影响呢?
目标序列 \(q\) 满足 \(q_{p_i}=i\),那么就是交换第 \(1/2\) 和第 \(3\)
那么就容易实现了,记录当前每一维分别是原来的哪一维及其偏移量即可
复杂度 \(O(n^2+m)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1010
#define ll long long
//#define int long long

int n, m;
char s[100010];
int a[N][N], b[N][N];
int tag[4], id[4], tem[4];

signed main()
{
	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &m);
		for (int i=0; i<n; ++i) for (int j=0; j<n; ++j) scanf("%d", &a[i][j]), --a[i][j];
		scanf("%s", s+1);
		for (int i=1; i<=3; ++i) tag[id[i]=i]=0;
		for (int i=1; i<=m; ++i) {
			if (s[i]=='R') ++tag[2];
			else if (s[i]=='L') --tag[2];
			else if (s[i]=='D') ++tag[1];
			else if (s[i]=='U') --tag[1];
			else if (s[i]=='I') swap(id[2], id[3]), swap(tag[2], tag[3]);
			else swap(id[1], id[3]), swap(tag[1], tag[3]);
		}
		for (int i=1; i<=3; ++i) tag[i]=(tag[i]%n+n)%n;
		for (int i=0; i<n; ++i) {
			for (int j=0; j<n; ++j) {
				tem[1]=i; tem[2]=j; tem[3]=a[i][j];
				b[(tem[id[1]]+tag[1])%n][(tem[id[2]]+tag[2])%n]=(tem[id[3]]+tag[3])%n;
			}
		}
		for (int i=0; i<n; ++i)
			for (int j=0; j<n; ++j)
				printf("%d%c", b[i][j]+1, " \n"[j==n-1]);
		printf("\n");
	}

	return 0;
}
posted @ 2022-06-25 15:10  Administrator-09  阅读(3)  评论(0编辑  收藏  举报