[NOIP2017模拟]裁剪表格
2017-10-20 21:33
393 查看
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(很爽有没有?完全无脑!)
100%链表正解(可以说,每一个有注释的地方,我都付出了沉痛的时间代价)
另附,标算代码(只记录下链表和右链表)
另附,指针写法
本题结。
样例数据
输入
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[dia 14a48 n1x][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 long using 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 ,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'); } }
本题结。
相关文章推荐
- NOIP模拟 裁剪表格【链表】
- [NOIP模拟][链表]裁剪表格
- 【jzoj5232】【NOIP2017模拟A组模拟8.5】【带权排序】【线段树】
- jzoj5249 【NOIP2017提高A组模拟8.10】文本编辑器 (序列修改类问题,数据结构)
- 拉格朗日插值法 【NOIP2017提高A组模拟10.6】Count
- [JZOJ5395]【NOIP2017提高A组模拟10.6】Count
- jzoj5399 【NOIP2017提高A组模拟10.7】Confess
- 【JZOJ 5405】【NOIP2017提高A组模拟10.10】Permutation
- JZOJ 100045. 【NOIP2017提高A组模拟7.13】好数
- 【jzoj5306】【NOIP2017提高A组模拟8.18】【棋盘游戏】
- JZOJ100047. 【NOIP2017提高A组模拟7.14】基因变异
- [JZOJ5402]【NOIP2017提高A组模拟10.8】God Knows (口胡)
- [NOIP2017模拟]弹球
- 世界线 【NOIP2017提高A组模拟8.22】
- [NOIP2017模拟]放盒子
- 【JZOJ5332】【NOIP2017提高A组模拟8.23】密码
- JZOJ5360. 【NOIP2017提高A组模拟9.12】Shorten Diameter
- [NOIP2017模拟]change
- [NOIP2017模拟]road
- 5368. 【NOIP2017提高A组模拟9.16】为逝去的公主献上的七重樱 单调队列