2018江苏冬令营5 交换矩阵
题目描述
SR得到了一个n*m的矩阵,矩阵行列从1开始标号,每个格子有不同的权值,Steam为了测试SR的智力,决定给他q个操作,每次操作交换两个大小一样的子矩阵,并在操作完之后输出它。
每个操作由6个正整数\(A_i,B_i,C_i,D_i,H_i,W_i\)组成,分别表示第一个子矩阵的左上角位于哪一行和哪一列、第二个的,以及两个子矩阵的行数和列数。操作保证两个矩阵没有重叠,矩阵的边也不会接壤,即没有任何一条格子的边同时属于两个子矩阵的边界。但是允许角接壤,即
SR不想算,请你帮他操作并输出。
输入
第一行三个正整数n,m,q,表示矩阵大小n*m,有q个操作。
接下来n行,每行m个数,表示矩阵每个格子的权值\(v_{i,j}\)。
再接下来q行,每行6个正整数,表示一个操作。
输出
共n行,每行m个数,表示操作后的矩阵
样例输入
4 4 2
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
1 1 3 3 2 2
3 1 1 3 2 2
样例输出
4 4 3 3
4 4 3 3
2 2 1 1
2 2 1 1
提示
30%的数据:n,m<=100,q<=500
100%的数据:n,m<=1000,q<=10000,\(|v_{i,j}|<=1e9\),保证修改的子矩阵在大矩阵内。
分析
- 可以把矩阵用类似于链表的一个东西来表示。每个节点都有一个编号,并在这个节点上记录它下边和右边的节点的编号。
- 每次修改时,我们只要修改矩阵四周的节点所指向的节点编号。
- 时间复杂度\(O(n^2+qn\))
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1050;
struct node{
int right,down,val;
}e[maxn*maxn*2];
int h[maxn],t[maxn],tot;
int tmp[maxn];
int main(){
int n,m,q;
scanf("%d%d%d", &n,&m,&q);
for(int i = 0; i <= n; ++i) h[i]=++tot;
for(int j = 1; j <= m; ++j) t[j]=++tot,tmp[j]=tot;
t[0]=h[0];
for(int i = 0; i <= n; ++i) e[h[i]].down=h[i+1];
for(int j = 0; j <= m; ++j) e[t[j]].right=t[j+1];
for(int i = 1; i <= n; ++i){
int p=h[i];
for(int j = 1; j <= m; ++j){
int x;
scanf("%d", &x);
++tot;
e[tot]=(node){0,0,x};
e[p].right=tot;
e[tmp[j]].down=tot;
p=tmp[j]=tot;
}
}
while(q--){
int a,b,c,d,H,W;
scanf("%d%d%d%d%d%d", &a,&b,&c,&d,&H,&W);
if(H==0||W==0) continue;
int x1=t[b-1],x2=t[b+W-1],x3=t[d-1],x4=t[d+W-1];
int v1=h[a-1],v2=h[a+H-1],v3=h[c-1],v4=h[c+H-1];
for(int i = 1; i <= a; ++i) x1=e[x1].down,x2=e[x2].down;
for(int i = 1; i <= c; ++i) x3=e[x3].down,x4=e[x4].down;
for(int j = 1; j <= b; ++j) v1=e[v1].right,v2=e[v2].right;
for(int j = 1; j <= d; ++j) v3=e[v3].right,v4=e[v4].right;
for(int i = 1; i <= H; ++i){
swap(e[x1].right,e[x3].right);
swap(e[x2].right,e[x4].right);
x1=e[x1].down;
x2=e[x2].down;
x3=e[x3].down;
x4=e[x4].down;
}
for(int i = 1; i <= W; ++i){
swap(e[v1].down,e[v3].down);
swap(e[v2].down,e[v4].down);
v1=e[v1].right;
v2=e[v2].right;
v3=e[v3].right;
v4=e[v4].right;
}
}
for(int i = 1; i <= n; ++i){
for(int j = e[h[i]].right; j ; j = e[j].right){
printf("%d%s", e[j].val,e[j].right?" ":"\n");
}
}
return 0;
}