Codeforces Round #367 (Div. 2) E. Working routine

13 篇文章 0 订阅
3 篇文章 0 订阅

原题网址: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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值