[NOIP2017模拟]裁剪表格

来源:互联网 发布:淘宝买家怎么快速升钻 编辑:程序博客网 时间:2024/05/25 23:57

2017.10.20 T3 1999

样例数据
输入

4 4 2
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
1 1 3 3 2 2
3 1 1 3 2 2

输出

4 4 3 3
4 4 3 3
2 2 1 1
2 2 1 1

分析:如果说把点暴力更换的话,是O(n2q)的复杂度。但是出题人wuvin目的是卡平衡树splay的,所以暴力反而跑得快得一匹,居然可以AC。我在他更换数据后也只被卡掉20分,但是如果加一个神奇的register(将频繁使用的变量放到寄存器中而不是内存,这样调用时非常快!但是不要用太多,会炸,我也不知道为什么),你也可以卡过,你看看这个时限4s的题,hyj大佬最后一个点的时间:
这里写图片描述
真是和时间赛跑的真男人,绝不超过4s!

之前的考试已经做过两道链表题了,这道的正解竟然也是链表(其实看看这复杂的转换也猜得到,果然wuvin对链表情有独钟),但是,升格为多向链表(记录上下左右的点的坐标,由于输出只需要向下的链和向右的链,所以也可以优化成只记录右和下的坐标),我是把map[0][1]作为基准点,每次的ri、ci就是基准点向下跳ri次再向右跳ci-1次就找到了需要修改的两个子矩阵的左上角那个点,然后就走一圈,把多向链表改接(实现极为复杂!!!我调了一个半小时,多谢Anonymous_jacklovecj的帮助,祝rp++),复杂度降为O(nq),但是考场上完全写不出来,我真的不想说什么了orz(也许该学学指针了,指针代码量少一半)。

代码
100%暴力+register(很爽有没有?完全无脑!)

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>#include<set>using namespace std;int getint(){    int sum=0,f=1;    char ch;    for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());    if(ch=='-')    {        f=-1;        ch=getchar();    }    for(;isdigit(ch);ch=getchar())        sum=(sum<<3)+(sum<<1)+ch-48;    return sum*f;}int n,m,q,r1,c1,r2,c2,h,w;int map[1010][1010];int main(){    freopen("table.in","r",stdin);    freopen("table.out","w",stdout);    n=getint(),m=getint(),q=getint();    for(register int i=1;i<=n;++i)        for(register int j=1;j<=m;++j)            map[i][j]=getint();    while(q--)    {        r1=getint(),c1=getint(),r2=getint(),c2=getint(),h=getint(),w=getint();        register int dx=r2-r1,dy=c2-c1;        for(register int i=r1;i<r1+h;++i)            for(register int j=c1;j<c1+w;++j)                swap(map[i][j],map[i+dx][j+dy]);    }    for(register int i=1;i<=n;++i)    {        for(register int j=1;j<m;++j)            cout<<map[i][j]<<" ";        cout<<map[i][m]<<'\n';    }    return 0;}

100%链表正解(可以说,每一个有注释的地方,我都付出了沉痛的时间代价)

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>#include<set>using namespace std;int getint(){    int sum=0,f=1;    char ch;    for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());    if(ch=='-')    {        f=-1;        ch=getchar();    }    for(;isdigit(ch);ch=getchar())        sum=(sum<<3)+(sum<<1)+ch-48;    return sum*f;}struct node{    int w;    int l[2],r[2],u[2],d[2];}map[1010][1010];int n,m,q,r1,c1,r2,c2,h,w;int main(){    freopen("table.in","r",stdin);    freopen("table.out","w",stdout);    n=getint(),m=getint(),q=getint();    for(int i=1;i<=n;++i)        for(int j=1;j<=m;++j)            map[i][j].w=getint();    for(int i=0;i<=n+1;++i)//在图外的一圈也要附上链表,之后转接才不会错        for(int j=0;j<=m+1;++j)//记录所有上下左右的横坐标、纵坐标......        {            map[i][j].r[0]=i,map[i][j].r[1]=j+1;            map[i][j].l[0]=i,map[i][j].l[1]=j-1;            map[i][j].u[0]=i-1,map[i][j].u[1]=j;            map[i][j].d[0]=i+1,map[i][j].d[1]=j;        }    while(q--)    {        r1=getint(),c1=getint(),r2=getint(),c2=getint(),h=getint(),w=getint();        int dian1x=0,dian1y=1,dian2x=0,dian2y=1,newx,newy;        for(int i=1;i<=r1;++i)//第一个矩阵先向下跳        {            newx=map[dian1x][dian1y].d[0];            newy=map[dian1x][dian1y].d[1];            dian1x=newx,dian1y=newy;        }        for(int i=1;i<c1;++i)//第一个矩阵再向右跳找到了左上角的点        {            newx=map[dian1x][dian1y].r[0];            newy=map[dian1x][dian1y].r[1];            dian1x=newx,dian1y=newy;        }        for(int i=1;i<=r2;++i)//第二个矩阵同理        {            newx=map[dian2x][dian2y].d[0];            newy=map[dian2x][dian2y].d[1];            dian2x=newx,dian2y=newy;        }        for(int i=1;i<c2;++i)        {            newx=map[dian2x][dian2y].r[0];            newy=map[dian2x][dian2y].r[1];            dian2x=newx,dian2y=newy;        }//绕着两个矩阵走一圈,把它们的最外面的一圈点相互转接        for(int i=1;i<=w;++i)//向右走长(后面代码块同理)        {            swap(map[dian1x][dian1y].u,map[dian2x][dian2y].u);//它们互换了位置,所以它们上面的点变成了对方的            map[map[dian1x][dian1y].u[0]][map[dian1x][dian1y].u[1]].d[0]=dian1x;//这几行就是把它们上面的点指向的下面的点改成互换后的点            map[map[dian1x][dian1y].u[0]][map[dian1x][dian1y].u[1]].d[1]=dian1y;            map[map[dian2x][dian2y].u[0]][map[dian2x][dian2y].u[1]].d[0]=dian2x;            map[map[dian2x][dian2y].u[0]][map[dian2x][dian2y].u[1]].d[1]=dian2y;//这里是在长上向右移动            if(i!=w)//只向右移w-1次就到边边上了,不能移出界了            {                newx=map[dian1x][dian1y].r[0];                newy=map[dian1x][dian1y].r[1];                dian1x=newx,dian1y=newy;                newx=map[dian2x][dian2y].r[0];                newy=map[dian2x][dian2y].r[1];                dian2x=newx,dian2y=newy;            }        }        for(int i=1;i<=h;++i)//向下走宽        {            swap(map[dian1x][dian1y].r,map[dian2x][dian2y].r);            map[map[dian1x][dian1y].r[0]][map[dian1x][dian1y].r[1]].l[0]=dian1x;            map[map[dian1x][dian1y].r[0]][map[dian1x][dian1y].r[1]].l[1]=dian1y;            map[map[dian2x][dian2y].r[0]][map[dian2x][dian2y].r[1]].l[0]=dian2x;            map[map[dian2x][dian2y].r[0]][map[dian2x][dian2y].r[1]].l[1]=dian2y;            if(i!=h)            {                newx=map[dian1x][dian1y].d[0];                newy=map[dian1x][dian1y].d[1];                dian1x=newx,dian1y=newy;                newx=map[dian2x][dian2y].d[0];                newy=map[dian2x][dian2y].d[1];                dian2x=newx,dian2y=newy;            }        }                                                                            for(int i=1;i<=w;++i)//向左走长        {            swap(map[dian1x][dian1y].d,map[dian2x][dian2y].d);            map[map[dian1x][dian1y].d[0]][map[dian1x][dian1y].d[1]].u[0]=dian1x;            map[map[dian1x][dian1y].d[0]][map[dian1x][dian1y].d[1]].u[1]=dian1y;            map[map[dian2x][dian2y].d[0]][map[dian2x][dian2y].d[1]].u[0]=dian2x;            map[map[dian2x][dian2y].d[0]][map[dian2x][dian2y].d[1]].u[1]=dian2y;            if(i!=w)            {                newx=map[dian1x][dian1y].l[0];                newy=map[dian1x][dian1y].l[1];                dian1x=newx,dian1y=newy;                newx=map[dian2x][dian2y].l[0];                newy=map[dian2x][dian2y].l[1];                dian2x=newx,dian2y=newy;            }        }        for(int i=1;i<=h;++i)//向上走宽        {            swap(map[dian1x][dian1y].l,map[dian2x][dian2y].l);            map[map[dian1x][dian1y].l[0]][map[dian1x][dian1y].l[1]].r[0]=dian1x;            map[map[dian1x][dian1y].l[0]][map[dian1x][dian1y].l[1]].r[1]=dian1y;            map[map[dian2x][dian2y].l[0]][map[dian2x][dian2y].l[1]].r[0]=dian2x;            map[map[dian2x][dian2y].l[0]][map[dian2x][dian2y].l[1]].r[1]=dian2y;            if(i!=h)            {                newx=map[dian1x][dian1y].u[0];                newy=map[dian1x][dian1y].u[1];                dian1x=newx,dian1y=newy;                newx=map[dian2x][dian2y].u[0];                newy=map[dian2x][dian2y].u[1];                dian2x=newx,dian2y=newy;            }        }    }    int dian1x=0,dian1y=1,dian2x,dian2y,newx,newy;    for(int i=1;i<=n;++i)    {        newx=map[dian1x][dian1y].d[0];//从基准点的下面一个点(也就是最后答案图的map[1][1])开始输出        newy=map[dian1x][dian1y].d[1];        dian1x=newx,dian1y=newy;        dian2x=dian1x,dian2y=dian1y;        for(int j=1;j<=m;++j)//输出、向右、输出、向右......        {                                                            cout<<map[dian2x][dian2y].w<<" ";            newx=map[dian2x][dian2y].r[0];            newy=map[dian2x][dian2y].r[1];            dian2x=newx,dian2y=newy;        }        cout<<'\n';    }    return 0;}

另附,标算代码(只记录下链表和右链表)

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<queue>#define ll long longusing namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());    if(c=='-')f=-1,c=getchar();    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int N=1005;int n,m,Q,num;int f[N*N][2],lab[N][N],v[N*N];int getlab(int a,int b){    int p=lab[0][0];    for(int i=1;i<=a;i++)p=f[p][1];    for(int i=1;i<=b;i++)p=f[p][0];    return p;}int main(){    freopen("table.in","r",stdin);    freopen("table.out","w",stdout);    int a,b,c,d,h,w;    n=getint(),m=getint(),Q=getint();    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            v[lab[i][j]=++num]=getint();    for(int i=0;i<=m+1;i++)        lab[0][i]=++num,lab[n+1][i]=++num;    for(int i=1;i<=n;i++)        lab[i][0]=++num,lab[i][m+1]=++num;    for(int i=0;i<=n;i++)        for(int j=0;j<=m;j++)        {            f[lab[i][j]][0]=lab[i][j+1];            f[lab[i][j]][1]=lab[i+1][j];        }    while(Q--)    {        a=getint(),b=getint(),c=getint(),d=getint(),h=getint(),w=getint();        int p1=getlab(a-1,b-1),p2=getlab(c-1,d-1);        int t1,t2,ww,hh;        for(t1=p1,t2=p2,ww=1;ww<=w;ww++)swap(f[t1=f[t1][0]][1],f[t2=f[t2][0]][1]);        for(hh=1;hh<=h;hh++)swap(f[t1=f[t1][1]][0],f[t2=f[t2][1]][0]);        for(t1=p1,t2=p2,hh=1;hh<=h;hh++)swap(f[t1=f[t1][1]][0],f[t2=f[t2][1]][0]);        for(ww=1;ww<=w;ww++)swap(f[t1=f[t1][0]][1],f[t2=f[t2][0]][1]);    }    for(int i=1,p=lab[0][0];i<=n;i++)    {        for(int j=1,t=p=f[p][1];j<=m;j++)            cout<<v[t=f[t][0]]<<" ";        cout<<'\n';    }    return 0;}

另附,指针写法

#include<bits/stdc++.h>using namespace std;inline int read(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;}const int Maxn=1e3+50;struct node{    node *right,*down;    int val;}Pool[Maxn*Maxn],*pool=Pool,*pos[Maxn][Maxn];inline node* newnode(int val){    ++pool;    pool->right=pool->down=NULL;    pool->val=val;    return pool;}int n,m,q;inline node* findpos(int x,int y){    node *now=pos[0][0];    for(register int i=1;i<=x;i++)now=now->down;    for(register int i=1;i<=y;i++)now=now->right;    return now;}inline void W(int x){    static int buf[50];    if(!x){putchar('0');return;}    if(x<0){putchar('-');x=-x;}    while(x){buf[++buf[0]]=x%10;x/=10;}    while(buf[0])putchar(buf[buf[0]--]+'0');}int main(){    n=read(),m=read(),q=read();    pos[0][0]=newnode(0);    for(register int i=1;i<=m;i++){        pos[0][i]=newnode(0);        pos[0][i-1]->right=pos[0][i];    }    for(register int i=1;i<=n;i++){        pos[i][0]=newnode(0);        pos[i-1][0]->down=pos[i][0];        for(register int j=1;j<=m;j++){            pos[i][j]=newnode(read());            pos[i-1][j]->down=pos[i][j];            pos[i][j-1]->right=pos[i][j];        }    }    for(register int i=1;i<=q;i++){        int dx1=read(),dy1=read(),dx2=read(),dy2=read(),h=read(),w=read();        node *lup1=findpos(dx1-1,dy1),*lup2=findpos(dx2-1,dy2);        node *lup3=findpos(dx1,dy1-1),*lup4=findpos(dx2,dy2-1);        node *ldown1=findpos(dx1+h-1,dy1),*ldown2=findpos(dx2+h-1,dy2);        node *rup1=findpos(dx1,dy1+w-1),*rup2=findpos(dx2,dy2+w-1);        for(register int j=1;j<=w;j++){            swap(lup1->down,lup2->down);            lup1=lup1->right,lup2=lup2->right;        }        for(register int j=1;j<=h;j++){            swap(lup3->right,lup4->right);            lup3=lup3->down,lup4=lup4->down;        }        for(register int j=1;j<=w;j++){            swap(ldown1->down,ldown2->down);            ldown1=ldown1->right,ldown2=ldown2->right;        }        for(register int j=1;j<=h;j++){            swap(rup1->right,rup2->right);            rup1=rup1->down,rup2=rup2->down;        }    }    for(register int i=1;i<=n;i++){        node *p=pos[i][0];        for(register int j=1;j<=m;j++){            p=p->right;            W(p->val);putchar(' ');        }        putchar('\n');    }}

本题结。

原创粉丝点击