描述:
题意:
给出一个矩阵和q个操作,每次操作需要交换矩阵的两个子矩形,问:经过q次操作后,最终矩阵长什么样子。
思路:
1000×1000 的矩阵啊, n2 操作肯定是要T的。考虑链表将整个矩阵串在一起,如下图:
发现对于任意需要我们交换的矩阵,其实我们只需要改变这两个矩阵的周围一圈元素的指针指向即可完成两个矩阵的交换。单次操作复杂度就降到了O(n + m)了。另外我们只需要知道元素的右边下边是什么,并不用关心上方,左方是什么,所以只用存储两个方向即可。
代码:
#include <bits/stdc++.h>
using namespace std;
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
const int N=1111;
struct P{
int val;
int dir[2]; // 0: right; 1: down
}p[N*N];
int m;
int change(int i,int j){
return i*m+j;
}
inline void Goto(int& pos,int x,int y){ //到指定点左上角
for(int i=1; i<x; i++)pos=p[pos].dir[1];
for(int i=1; i<y; i++)pos=p[pos].dir[0];
}
inline void shift(int p1, int p2,int h,int w,int s){
for(int i=0; i<h; i++){
p1=p[p1].dir[s];
p2=p[p2].dir[s];
swap(p[p1].dir[1-s], p[p2].dir[1-s]);
}
s=1-s;
for(int i=0; i<w; i++){
p1=p[p1].dir[s];
p2=p[p2].dir[s];
swap(p[p1].dir[1-s], p[p2].dir[1-s]);
}
}
int main(){
int n,q; read(n);read(m);read(q);
for(int i=1; i<=n ;i++)
for(int j=1; j<= m; j++)
read(p[change(i, j)].val);
for(int i=0; i<=n ;i++){
for(int j=0; j<=m ; j++){
p[change(i, j)].dir[0]=change(i, j+1);
p[change(i, j)].dir[1]=change(i+1, j);
}
}
int x1,x2,y1,y2,h,w;
while(q--){
read(x1);read(y1);read(x2);read(y2);read(h);read(w);
int p1=0,p2=0;
Goto(p1, x1, y1);
Goto(p2, x2, y2);
shift(p1, p2, h, w, 1);
shift(p1, p2, w, h, 0);
}
int pos=0;
for(int i=1; i<=n; i++){
pos=p[pos].dir[1];
int tmp=pos;
for(int j=1; j<=m; j++){
tmp=p[tmp].dir[0];
printf("%d ",p[tmp].val);
}
puts("");
}
return 0;
}