JZOJ5281. 【NOIP提高组模拟A组8.15】钦点

本文介绍了一种使用链表维护的矩阵元素交换算法,通过仅修改边界元素的指针实现两个矩形区域内的元素交换。文章详细解释了如何用两个指针(向右和向下)来简化每个位置的连接,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写图片描述
这里写图片描述

分析

这题很显然要用链表来维护。
有的人觉得每个位置要用4个指针,
其实只需要两个,一个是向右,一个向下。

交换的时候改一下边界的一圈即可。
两个矩形外的左边那一列的右指针交换,
两个矩形外的上面那一排的下指针交换。

两个矩形内的最右边的一列的右指针交换,
两个矩形内的最下面的一排的下指针交换。

最后输出就按照指针来就可以了。

code

#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 1003
#define db double
#define P putchar
#define G getchar
#define mo 1000000007
using namespace std;

struct node
{
    int r,d,st,len;
}a[N*N];
char s[N*N*10],ch;
int n,m,x,y,xx,yy,l1,l2,len,q;
int p1,p2,p3,p4,pp1,pp2,pp3,pp4;
int g[N][N],tot;

void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=G();
    n*=w;
}

int find(int x,int y)
{
    int i=g[0][0];
    while(x--)i=a[i].d;
    while(y--)i=a[i].r;
    return i;
}

int main() 
{
    read(n);read(m);read(q);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            g[i][j]=++tot;

    for(int i=n;i;i--)
        g[i][0]=++tot,a[g[i][0]].d=g[i+1][0],a[g[i][0]].r=g[i][1];

    for(int i=m;i>=0;i--)
        g[0][i]=++tot,a[g[0][i]].d=g[1][i],a[g[0][i]].r=g[0][i+1];

    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            x=g[i][j];
            a[x].r=g[i][j+1];
            a[x].d=g[i+1][j];
            a[x].st=len+1;
            a[x].len=0;
            ch=getchar();
            while('a'>ch || ch>'z')ch=getchar();
            while('a'<=ch && ch<='z')
            {
                s[++len]=ch;
                a[x].len++;
                ch=getchar();
            }
        }

    while(q--)
    {
        read(x);read(y);read(xx);read(yy);read(l1);read(l2);

        p1=find(x,y-1);
        p2=find(x,y+l2-1);
        p3=find(xx,yy-1);
        p4=find(xx,yy+l2-1);

        pp1=find(x-1,y);
        pp2=find(x+l1-1,y);
        pp3=find(xx-1,yy);
        pp4=find(xx+l1-1,yy);

        for(int i=1;i<=l1;i++)
        {
            swap(a[p1].r,a[p3].r);
            swap(a[p2].r,a[p4].r);

            p1=a[p1].d;
            p2=a[p2].d;
            p3=a[p3].d;
            p4=a[p4].d;
        }


        for(int i=1;i<=l2;i++)
        {
            swap(a[pp1].d,a[pp3].d);
            swap(a[pp2].d,a[pp4].d);

            pp1=a[pp1].r;
            pp2=a[pp2].r;
            pp3=a[pp3].r;
            pp4=a[pp4].r;
        }

    }

    for(int i=1;i<=n;i++)
    {
        x=find(i,1);
        for(int j=1;j<=m;j++)
        {
            for(int k=a[x].st;k<a[x].st+a[x].len;k++)
                P(s[k]);
            P(' ');
            x=a[x].r;
        }
        P('\n');
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值