CF1458C Latin Square

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1458C Latin Square相关的知识,希望对你有一定的参考价值。

CF1458C Latin Square

题意:

T 组测试数据,每次给一个 n × n n\\times n n×n 的矩阵,每行每列都是个 1 → n 1\\to n 1n 的排列。有 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 1in 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。 1T10001n10001m1051ai,jn

题解:

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的主要内容,如果未能解决你的问题,请参考以下文章

CF1207B Square Filling

CF1A-Theatre Square

CF 711B - Chris and Magic Square

题解 CF1359B New Theatre Square

题解 CF1359B New Theatre Square

Square Root of Permutation - CF612E