CF1458C Latin Square
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1458C Latin Square相关的知识,希望对你有一定的参考价值。
题意:
T 组测试数据,每次给一个
n
×
n
n\\times n
n×n 的矩阵,每行每列都是个
1
→
n
1\\to n
1→n 的排列。有 m 次操作,如果是 UDLR 就是要把整个矩阵每行/每列往一个方向循环移动一格。如果是 IC,就是把矩阵每行/每列变成原来的逆排列。求最后的矩阵。
逆排序定义:
一个序列
p
1
,
p
2
,
.
.
.
.
,
p
n
p_{1},p_{2},....,p_{n}
p1,p2,....,pn的逆排序是
q
1
,
q
2
,
.
.
.
q
n
q_{1},q_{2},...q_{n}
q1,q2,...qn,对于所有
1
≤
i
≤
n
1\\le i\\le n
1≤i≤n有
p
q
i
=
i
p_{q_{i}}=i
pqi=i
数 据 范 围 : 1 ≤ T ≤ 1000 , 1 ≤ ∑ n ≤ 1000 , 1 ≤ ∑ m ≤ 1 0 5 , 1 ≤ a i , j ≤ n 。 数据范围:1\\le T\\le 1000,1\\le \\sum n\\le 1000,1\\le \\sum m\\le 10^5 ,1\\le a_{i,j}\\le n。 数据范围:1≤T≤1000,1≤∑n≤1000,1≤∑m≤105,1≤ai,j≤n。
题解:
UDLR都好操作,我们只需要维护x和y分别移动了多少即可
但问题就是存在IC操作,就是这个逆排序如何理解?
对于排序
p
1
,
p
2
,
.
.
.
.
,
p
n
p_{1},p_{2},....,p_{n}
p1,p2,....,pn,我们可以把每个元素看作是一个二维坐标
(
i
,
p
i
)
(i,p_{i})
(i,pi),那么这个排序的逆元相当于
(
p
i
,
i
)
(p_{i},i)
(pi,i),即交换两维坐标
那么我们就可以把这个矩阵看作是三维空间里的点
(
x
,
y
,
a
x
,
y
)
(x,y,a_{x,y})
(x,y,ax,y),
I
I
I操作就是交换x和
a
x
,
y
a_{x,y}
ax,y,
C
C
C操作就是交换了y和
a
x
,
y
a_{x,y}
ax,y,LRUD就是正常的对x或y的修改
这样,对于LRUD,记录每一维的增量,对于IC,记录当前每一维是原来的第几维,这样不就将所有操作O(1)解决了吗
我们用数组p来记录当前是第几维,I,C操作就是交换数组p
秒啊~这个题
详细看代码
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
x= 0;
char c= getchar();
bool flag= 0;
while (c < '0' || c > '9')
flag|= (c == '-'), c= getchar();
while (c >= '0' && c <= '9')
x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
if (flag)
x= -x;
read(Ar...);
}
template <typename T> inline void write(T x)
{
if (x < 0) {
x= ~(x - 1);
putchar('-');
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
startTime = clock ();
freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
endTime= clock();
printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn=2e3+9;
int a[maxn*maxn][3];
int b[maxn][maxn];
int p[3];
int x[3];
int n,m;
void add(int &x){//正向移动
x++;
if(x>n)x-=n;
}
void del(int &x){//方向移动
x--;
if(x<0)x+=n;
}
void solve(){
read(n,m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++){
int pos=(i-1)*n+j;
int x;
read(x);
a[pos][0]=i;
a[pos][1]=j;
a[pos][2]=x;
//存下三维信息
}
}
for(int i=0;i<3;i++){
p[i]=i;
x[i]=0;
}
string s;
cin>>s;
for(int i=0;i<m;i++){
if(s[i]=='U')del(x[p[0]]);//行--
if(s[i]=='D')add(x[p[0]]);//行++
if(s[i]=='L')del(x[p[1]]);//列--
if(s[i]=='R')add(x[p[1]]);//列++
if(s[i]=='I')swap(p[1],p[2]);//行逆排序,将列与值交换
if(s[i]=='C')swap(p[0],p[2]);//列逆排序
}
for(int i=1;i<=n*n;i++){
for(int j=0;j<3;j++)//执行对应操作
a[i][j]=(a[i][j]+x[j]-1)%n+1;
b[a[i][p[0]]][a[i][p[1]]]=a[i][p[2]];//将变换后的值赋给b
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%d ",b[i][j]);
}
printf("\\n");
}
}
int main()
{
rd_test();
int t;
read(t);
while(t--){
solve();
}
//Time_test();
}
以上是关于CF1458C Latin Square的主要内容,如果未能解决你的问题,请参考以下文章