原题网址:http://codeforces.com/contest/706/problem/E
用四向链表维护每个点上下左右分别是哪些点,每次修改只要修改矩形周围一圈,复杂度O(q(n+m))。
然而Pascal四向链表强行被卡T,改成双向链表(向右和向下)才卡过(估计下来此题Pascal有C++4倍常数左右)。
里面有好几处精妙细节,所以我不得不标记出来以免我以后注意不到。
//四向链表
var
lf,rt,up,dn,v:array[-1..1010001] of longint;
n,m,q,i,j,p,p1,p2,a,b,c,d,e,f:longint;
function zb(x,y:longint):longint;
begin exit(x*(m+2)+y);end;
function getpos(a,b:longint):longint;
var
p:longint;
begin
p:=0;
for i:=1 to a do p:=dn[p];
for i:=1 to b do p:=rt[p];
exit(p);
end;
procedure swap(var a,b:longint);
var
t:longint;
begin
t:=a;a:=b;b:=t;
end;
begin
read(n,m,q);
for i:=1 to n do
for j:=1 to m do
read(v[zb(i,j)]);
for i:=0 to n+1 do
for j:=0 to m+1 do
begin
if j>0 then lf[zb(i,j)]:=zb(i,j-1);
if j<m+1 then rt[zb(i,j)]:=zb(i,j+1);
if i>0 then up[zb(i,j)]:=zb(i-1,j);
if i<n+1 then dn[zb(i,j)]:=zb(i+1,j);
end;//外围要多开一圈(否则外面和一圈0交换信息就会出错!),数组也要开大,zb函数也要注意
repeat
read(a,b,c,d,e,f);dec(q);
p1:=getpos(a,b);p2:=getpos(c,d);
for i:=1 to f do
begin
swap(dn[up[p1]],dn[up[p2]]);
swap(up[p1],up[p2]);
if i<f then p1:=rt[p1];
if i<f then p2:=rt[p2];
end;
for i:=1 to e do
begin
swap(lf[rt[p1]],lf[rt[p2]]);
swap(rt[p1],rt[p2]);
if i<e then p1:=dn[p1];
if i<e then p2:=dn[p2];
end;
for i:=1 to f do
begin
swap(up[dn[p1]],up[dn[p2]]);
swap(dn[p1],dn[p2]);
if i<f then p1:=lf[p1];
if i<f then p2:=lf[p2];
end;
for i:=1 to e do
begin
swap(rt[lf[p1]],rt[lf[p2]]);
swap(lf[p1],lf[p2]);
if i<e then p1:=up[p1];
if i<e then p2:=up[p2];
end;
until q=0;
for i:=1 to n do
begin
p:=0;
for j:=1 to i do p:=dn[p];
for j:=1 to m-1 do
begin
p:=rt[p];
write(v[p],' ');
end;
p:=rt[p];
writeln(v[p]);
end;
close(input);close(output);
end.
//双向链表
var
rt,dn,v:array[-1..1010001] of longint;
n,m,q,i,j,p,p1,p2,g1,g2,a,b,c,d,e,f:longint;
function zb(x,y:longint):longint;
begin exit(x*(m+1)+y);end;
function getpos(a,b:longint):longint;
var
p:longint;
begin
p:=0;
for i:=1 to a do p:=dn[p];
for i:=1 to b do p:=rt[p];
exit(p);
end;
procedure swap(var a,b:longint);
var
t:longint;
begin
t:=a;a:=b;b:=t;
end;
begin
read(n,m,q);
for i:=1 to n do
for j:=1 to m do
read(v[zb(i,j)]);
for i:=0 to n do
for j:=0 to m do
begin
rt[zb(i,j)]:=zb(i,j+1);
dn[zb(i,j)]:=zb(i+1,j);
end;//外围只要多开左上角,因为右下角用不到
repeat
read(a,b,c,d,e,f);dec(q);
g1:=getpos(a-1,b-1);g2:=getpos(c-1,d-1);//一定要记下来,不然第二次找会找不到
p1:=g1;p2:=g2;
for i:=1 to e do
begin
p1:=dn[p1];
p2:=dn[p2];
swap(rt[p1],rt[p2]);
end;
for i:=1 to f do
begin
p1:=rt[p1];
p2:=rt[p2];//当i=1也就是第一步向右走时,其实p1,p2偷偷交换了位置,但这并不影响交换
swap(dn[p1],dn[p2]);
end;
p1:=g1;p2:=g2;
for i:=1 to f do
begin
p1:=rt[p1];
p2:=rt[p2];
swap(dn[p1],dn[p2]);
end;
for i:=1 to e do
begin
p1:=dn[p1];
p2:=dn[p2];
swap(rt[p1],rt[p2]);
end;
until q=0;
for i:=1 to n do
begin
p:=0;
for j:=1 to i do p:=dn[p];
for j:=1 to m-1 do
begin
p:=rt[p];
write(v[p],' ');
end;
p:=rt[p];
writeln(v[p]);
end;
close(input);close(output);
end.