左移右移
题目描述
小蓝有一个长度为 N 的数组, 初始时从左到右依次是 1,2,3,…N 。之后小蓝对这个数组进行了 M 次操作, 每次操作可能是以下 2 种之一:
左移 x, 即把 x 移动到最左边。
右移 x, 即把 x 移动到最右边。
请你回答经过 M 次操作之后, 数组从左到右每个数是多少?
输入格式
第一行包含 2 个整数, N* 和 M 。
以下 M 行每行一个操作, 其中 “L x "表示左移 x,"Rx "表示右移 x 。
输出格式
输出 N* 个数, 代表操作后的数组。
样例输入
5 3
L 3
L 2
R 1
样例输出
2 3 4 5 1
样例说明
样例中的数组变化如下:
[1,2,3,4,5]→[3,1,2,4,5]→[2,3,1,4,5]→[2,3,4,5,1]
评测用例规模与约定
对于 50%50% 的评测用例, 1≤N,M≤10000.
对于 100%100% 的评测用例, 1≤N,M≤200000,1≤x≤N.
代码
#include<stdio.h>
int sign[200004][3];
int main(){
int n,m,t;
char x;
scanf("%d %d\n",&n,&m);
//初始化建立数组链表
for(int i=0;i<=n+1;i++){
sign[i][0]=i; //每一个一维数组第一个表示要存入的数
sign[i][1]=i-1; //第二个表示前一个节点的序号 (前指针)
sign[i][2]=i+1; //第三个表示后一个节点的序号 (后指针)
}
int l,r;
while(m--){
//例如数组初始化为 1 2 3 4 5 (数组中实际存放为 0 1 2 3 4 5 6)
scanf("%c %d\n",&x,&t);
if(x=='L'){ //例如输入 L 3
l=sign[t][1]; //将节点 3 的前一个节点赋值给 l
r=sign[t][2]; //将节点 3 的后一个节点赋值给 r
//删除节点 3(并不是真删除,只是修改前后指针使节点3不在原来的位置)
sign[l][2]=r; //将节点 3 的前一个节点(节点 2) 的后指针指向节点 4
sign[r][1]=l; //将节点 3 的后一个节点(节点 4) 的前指针指向节点 2
//将节点 3 插入前面
sign[t][1]=0; //将节点 3 的前指针指向节点 0
sign[t][2]=sign[0][2]; //将节点 3 的后指针指向节点 0 的后继节点(节点 1)
sign[sign[0][2]][1]=t; //将节点 0 的后继节点(节点 1)的前指针指向节点 3
sign[0][2]=t; //将节点 0 的后指针指向节点 3
}
else{ //例如输入 R 3
l=sign[t][1];
r=sign[t][2];
sign[l][2]=r;
sign[r][1]=l;
//将节点 3 插入后面
sign[t][2]=n+1; //将节点 3 的后指针指向节点 6
sign[t][1]=sign[n+1][1]; //将节点 3 的前指针指向节点 6 的前驱节点(节点 5)
sign[sign[n+1][1]][2]=t; //将节点 6 的前驱节点(节点 5)的后指针指向节点 3
sign[n+1][1]=t; //将节点 6 的前指针指向节点 3
}
}
int i=sign[0][2];
while(i<=n){
printf("%d ",i);
i=sign[i][2];
}
return 0;
}