cf#367E-Working routine 十字链表

http://codeforces.com/contest/706/problem/E

题意:给你一个矩阵,要你进行q次操作,输出最后的矩阵

操作:选择两个子矩阵交换,保证两个子矩阵没有边的接触。

数据范围

Input

The first line of the input contains three integers nm and q (2 ≤ n, m ≤ 10001 ≤ q ≤ 10 000) — the number of rows and columns in matrix, and the number of tasks Vasiliy has to perform.

Then follow n lines containing m integers vi, j (1 ≤ vi, j ≤ 109) each — initial values of the cells of the matrix.

Each of the following q lines contains six integers aibicidihiwi (1 ≤ ai, ci, hi ≤ n1 ≤ bi, di, wi ≤ m).

Output

Print n lines containing m integers each — the resulting matrix.


看这个数据范围。。。。似乎可以强行用splay交换怼过去???据说会T。。。


官解是十字链表搞,如果建立好十字链表后

每次交换矩阵,其实变化的之后该子矩阵的周围一圈的指针。那么我们只需要暴力修改这一圈指针即可,复杂度O(n+m)


并且可以发现,只需要维护一个right和down指针即可。

如果加多一个up,left指针也没问题,如果是只用r和d的话,需要给原矩阵周围覆盖多一圈,以免越界


并且题目说了子矩阵是不会挨在一起的,那么就更不容易越界啦,

(当然即使挨在一起也是可以做得,例如,A矩阵的最后一列与B矩阵的第一列挨着,那么暴力交换掉两个矩阵的最后一列,剩下的矩阵再按正常方法交换即可,复杂度不变)


amazing



#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
typedef long long  ll;
struct node
{
    int v;
    node *r,*d;
};
node aa[1005][1005];
int main()
{

    int n,m,q;
    cin>>n>>m>>q;
    for (int i=0; i<=n; i++) aa[i][0].r=&aa[i][1];
    for (int i=0; i<=m; i++) aa[0][i].d=&aa[1][i];
    for (int i=1; i<=m; i++) aa[0][i].r=&aa[0][i+1];
    for (int i=1; i<=n; i++) aa[i][0].d=&aa[i+1][0];

    for (int i=1; i<=n; i++)
        for (int j=1; j<=m; j++)
        {
            scanf("%d",&aa[i][j].v);
            aa[i][j].r=&aa[i][j+1];
            aa[i][j].d=&aa[i+1][j];
        }

    int a,b,c,d,h,w;
    while(q--)
    {
        scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&h,&w);
        node *p1,*p2,*p3,*p4;
        p3=&aa[a-1][0];
        p4=&aa[c-1][0];
        for (int i=1; i<b; i++) p3=p3->r;
        for (int i=1; i<d; i++) p4=p4->r;

        p1=p3->r,p2=p4->r;
        for (int i=1; i<=w; i++)
        {
            swap(p1->d,p2->d);
            if (i<w)
            {
                p1=p1->r;
                p2=p2->r;
            }
        }
        p1=p1->d,p2=p2->d;
        for (int i=1; i<=h; i++)
        {
            swap(p1->r,p2->r);
            p1=p1->d;
            p2=p2->d;
        }

        p1=p3->d,p2=p4->d;
        for (int i=1; i<=h; i++)
        {
            swap(p1->r,p2->r);
            if (i<h)
            {
                p1=p1->d;
                p2=p2->d;
            }
        }
        p1=p1->r,p2=p2->r;
        for (int i=1; i<=w; i++)
        {
            swap(p1->d,p2->d);
            p1=p1->r;
            p2=p2->r;
        }

    }
    node *p;
    for (int i=1; i<=n; i++)
    {
        p=aa[i][0].r;
        for (int j=1; j<=m; j++)
        {
            printf("%d ",p->v);
            p=p->r;
        }
        printf("\n");
    }
    printf("\n");


    return 0;

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值