原题网址: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.