CF 706E Working routine

description

题意就是一开始给出一个n*m的矩阵,然后有Q操作,每次把这个矩阵中的两个子矩阵的所有值交换,这两个子矩阵不能相交。输出最后矩阵的形态。(2 ≤ n, m ≤ 1000, 1 ≤ q ≤ 10 000)

Solution

一开始本来想用splay来处理的,对于每一行的处理,直接弄一下就好,所以复杂度为O(NQ log N),由于时限为2.5s,所以勉强卡过。
但后来才发现有更简单的解法。。。
对于一次操作,会对一个位置的上下左右产生影响,你会发现,这些位置刚好分布在要交换矩阵的四条边上和它的上下两行前后两列。但记录一个位置的左边和这个位置的左边记录他的右边是等价的,所以我们省去两个,只记录一个位置的右边和下边分别是什么,那么对于一次交换,设第一个矩形左上角坐标为(x,y),第二个矩形左上角为(xx,yy),矩形长为L,宽为W,我们只要更新第x-1行、x+L-1行和xx-1行、xx+L-1行的下边的坐标和第y-1列、yy+W-1行和yy-1列、yy+W-1行的右边的值即可。值得注意的是,我们一开始并不知道现在(x-1,y-1)坐标上和(xx-1,yy-1)坐标上的是原图中什么坐标,所以我们先从(0,0)走起,往下走x-1行,往左走y-1列,就可得知现在(x-1,y-1)坐标上原图中什么坐标,(xx-1,yy-1)同理。
最后,只需从(0,0)把原图遍历一遍即可得到现在的矩形。

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1005;
struct code{
    int dx,dy,rx,ry;
}f[maxn][maxn];
int n,m,i,t,j,k,l,x,y,xx,yy,h,w,c[maxn][maxn],d[maxn][maxn],bz[maxn][maxn],num,t1,k1,a,b,a1,b1;
int p,q,p1,q1,q2;
void dg(int x,int y,int x1,int y1){
    if (bz[x][y]) return;
    bz[x][y]=1;
    d[x1][y1]=c[x][y];
    dg(f[x][y].dx,f[x][y].dy,x1+1,y1);
    dg(f[x][y].rx,f[x][y].ry,x1,y1+1);
}
int main(){
//  freopen("data.in","r",stdin);
    scanf("%d%d%d",&n,&m,&q2);
    for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
            scanf("%d",&c[i][j]);
    for (i=0;i<=n;i++)
        for (j=0;j<=m;j++)
            f[i][j].dx=i+1,f[i][j].dy=j;
    for (i=0;i<=n;i++)
        for (j=0;j<=m;j++)
            f[i][j].rx=i,f[i][j].ry=j+1;
    for (j=1;j<=q2;j++){
        scanf("%d%d%d%d%d%d",&x,&y,&xx,&yy,&h,&w);
        a=0;b=0;
        for (i=1;i<x;i++)
            t=a,a=f[a][b].dx,b=f[t][b].dy;
        for (i=1;i<y;i++)
            t=a,a=f[a][b].rx,b=f[t][b].ry;
        a1=0,b1=0;
        for (i=1;i<xx;i++)
            t=a1,a1=f[a1][b1].dx,b1=f[t][b1].dy;
        for (i=1;i<yy;i++)
            t=a1,a1=f[a1][b1].rx,b1=f[t][b1].ry;
        t=a,k=b;
        t1=a1;k1=b1;
        for (i=1;i<=w;i++){
            l=t,t=f[t][k].rx,k=f[l][k].ry;
            l=t1,t1=f[t1][k1].rx,k1=f[l][k1].ry;
            if (i==w){
                p=t,q=k,p1=t1,q1=k1;
                continue;
            }
            swap(f[t][k].dx,f[t1][k1].dx);
            swap(f[t][k].dy,f[t1][k1].dy);
        }
        for (i=1;i<=h;i++){
            l=t,t=f[t][k].dx,k=f[l][k].dy;
            l=t1,t1=f[t1][k1].dx,k1=f[l][k1].dy;
            swap(f[t][k].rx,f[t1][k1].rx);
            swap(f[t][k].ry,f[t1][k1].ry);
        }
        swap(f[p][q].dx,f[p1][q1].dx);
        swap(f[p][q].dy,f[p1][q1].dy);
        t=a,k=b;
        t1=a1;k1=b1;
        for (i=1;i<=h;i++){
            l=t,t=f[t][k].dx,k=f[l][k].dy;
            l=t1,t1=f[t1][k1].dx,k1=f[l][k1].dy;
            if (i==h){
                p=t,q=k,p1=t1,q1=k1;
                continue;
            }
            swap(f[t][k].rx,f[t1][k1].rx);
            swap(f[t][k].ry,f[t1][k1].ry);
        }
        for (i=1;i<=w;i++){
            l=t,t=f[t][k].rx,k=f[l][k].ry;
            l=t1,t1=f[t1][k1].rx,k1=f[l][k1].ry;
            swap(f[t][k].dx,f[t1][k1].dx);
            swap(f[t][k].dy,f[t1][k1].dy);
        }
        swap(f[p][q].rx,f[p1][q1].rx);
        swap(f[p][q].ry,f[p1][q1].ry);
    }
    dg(0,0,0,0);
    for (i=1;i<=n;i++){
        for (j=1;j<=m;j++)
            printf("%d ",d[i][j]);
        printf("\n");
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值