问题描述
体育老师小明要将自己班上的学生按顺序排队。他首先让学生按学号从小到大的顺序排成一排,学号小的排在前面,然后进行多次调整。一次调整小明可能让一位同学出队,向前或者向后移动一段距离后再插入队列。
例如,下面给出了一组移动的例子,例子中学生的人数为8人。
0)初始队列中学生的学号依次为1, 2, 3, 4, 5, 6, 7, 8;
1)第一次调整,命令为“3号同学向后移动2”,表示3号同学出队,向后移动2名同学的距离,再插入到队列中,新队列中学生的学号依次为1, 2, 4, 5, 3, 6, 7, 8;
2)第二次调整,命令为“8号同学向前移动3”,表示8号同学出队,向前移动3名同学的距离,再插入到队列中,新队列中学生的学号依次为1, 2, 4, 5, 8, 3, 6, 7;
3)第三次调整,命令为“3号同学向前移动2”,表示3号同学出队,向前移动2名同学的距离,再插入到队列中,新队列中学生的学号依次为1, 2, 4, 3, 5, 8, 6, 7。
小明记录了所有调整的过程,请问,最终从前向后所有学生的学号依次是多少?
请特别注意,上述移动过程中所涉及的号码指的是学号,而不是在队伍中的位置。在向后移动时,移动的距离不超过对应同学后面的人数,如果向后移动的距离正好等于对应同学后面的人数则该同学会移动到队列的最后面。在向前移动时,移动的距离不超过对应同学前面的人数,如果向前移动的距离正好等于对应同学前面的人数则该同学会移动到队列的最前面。
输入格式
输入的第一行包含一个整数n,表示学生的数量,学生的学号由1到n编号。
第二行包含一个整数m,表示调整的次数。
接下来m行,每行两个整数p, q,如果q为正,表示学号为p的同学向后移动q,如果q为负,表示学号为p的同学向前移动-q。
输出格式
输出一行,包含n个整数,相邻两个整数之间由一个空格分隔,表示最终从前向后所有学生的学号。
样例输入
8
3
3 2
8 -3
3 -2
样例输出
1 2 4 3 5 8 6 7
评测用例规模与约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 1000,所有移动均合法。
思路:这个题目如果用py解决非常容易,可以用List等去模拟这种向前和向后移动的问题,用c++解决也会简单的,但由于自己不熟练,因此选择了用c语言解决,自己思路最开始一直不清楚,后面理了很久,才清晰一点。我的思路主要是设置两个数组,一个每个位置对应编号,一个就是编号所对应的位置,每次移一个编号,位置和编号数组都进行对应的更新。但我第一次提交只有30分,只因为有一个循环取了等号,导致部分数据错误。因此正常考试的时候,一定要想起清楚思路,不能抱着试一下的态度去做,因为当时是不能立刻知道结果的。循环一定要自己手动模拟一下。具体可看下面代码,有注解,
代码:
#include<stdio.h>
int main(){
int n,m;
int i,j,index,num;
int a[1001]={0};//记录每个编号的位置
int b[1001]={0};//记录每个位置上面的编号
scanf("%d",&n);
scanf("%d",&m);
int flag=0;
for(i=1;i<=n;i++){
a[i]=i;
b[i]=i;
}
for(i=0;i<m;i++){
scanf("%d%d",&index,&num);
a[index]=a[index]+num;
if(num>0){//向前移动 ,对这中间的位置对应的编号进行调整
for(j=a[index]-num;j<a[index];j++){//注意这里前往别加等号,如果加了等号,虽然对b[j]影响不大,后面改过来了,但是对 a[b[j]]后面没有改,第一次提交就是这里加了等号猜错的。
b[j]=b[j+1];
a[b[j]]=j;
}
b[a[index]]=index;
}else{
for(j=a[index]-num-1;j>=a[index];j--){
b[j+1]=b[j];
a[b[j+1]]=j+1;
}
b[a[index]]=index;
}
// a[index]=0;
}
for(i=1;i<=n;i++){
if(i==1)
printf("%d",b[i]);
else printf(" %d",b[i]);
}
return 0;
}