题解 [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;
}