这一题我们先看数据范围,N<=10000 ,我们可以知道,是不可以拿一个二维数组去记录每一个点的,而且时间复杂度也不可以依赖于N,所以我们只能从K下手,对于每一次询问,其实答案非常好算,但是比较难的是每次算出答案后,进行的操作对其他数初始位置的影响,我们可以设置两个结构体数组x[i]和y[i],分别有move,now两个元素。表示第i次询问,在x和y轴方向分别移动了多少,x[i].now表示这一次操作,x移动的是哪一行(因为移动的是一行,所以要用y来表示是哪一行,因为只有y相同,x不相同),move说明向右移了多少,y[i].now表示这次操作移动的是哪一列(同样,一列上的数,x相同,y不相同,所以用x表示),move表示移动了多少,因为题目上规定了先向右移,再向下移,所以我们先计算这一次操作的行,在计算列。
我们在每一次新的操作时,将以前操作时保存下来的哪一行哪一列移动了多少,一个一个遍历以求出这个数现在真实的位置,在进行计算。
对于计算时非常简单的,分两种情况,1-将要达到的坐标比现在的坐标大(x坐标,y坐标同时适用),那么直接相减得到的差就是要进行多少次操作,知道xy都达到要求,就可以输出答案。2-即将要达到的坐标比现在的坐标小,我们的操作只能向下向后走,无法回头,只能到达边界后回到第一格,转化成问题1。
Code:
#include<iostream> #include<cstdio> using namespace std; struct number{ long long move; long long now; }x[1010],y[1010]; long long n,k,x2,y2; long long num[1010],x1[1010],y1[1010],ans; int main(){ ios::sync_with_stdio(false); cin>>n>>k; for(int i=1;i<=k;i++) cin>>num[i]>>y1[i]>>x1[i]; for(int i=1;i<=k;i++){ ans=0; x2=num[i]%n; if(num[i]%n==0) x2=n; y2=num[i]/n; if(num[i]%n!=0) y2++; for(int j=1;j<i;j++){ if(x[j].now==y2){ x2=(x[j].move+x2)%n; if(x2==0) x2=n; } if(y[j].now==x2){ y2=(y[j].move+y2)%n; if(y2==0) y2=n; } } if(x1[i]<x2){ ans+=n-x2+x1[i]; x[i].move=n-x2+x1[i]; x[i].now=y2; } else if(x1[i]>x2){ ans+=x1[i]-x2; x[i].move=x1[i]-x2; x[i].now=y2; } if(y1[i]<y2){ ans+=n-y2+y1[i]; y[i].move=n-y2+y1[i]; y[i].now=(x2+x[i].move)%n; if(y[i].now==0) y[i].now=n; } else if(y1[i]>y2){ ans+=y1[i]-y2; y[i].move=y1[i]-y2; y[i].now=(x2+x[i].move)%n; if(y[i].now==0) y[i].now=n; } cout<<ans<<endl; } }
谢谢阅读。