题目描述 Description
又一个学期结束了,又积累了好多本书,你决定好好整理一下,整理时共有
三种操作,规则如下:
1,p 表示把编号为 p 的书放到最前面;
2,p 表示把编号为 p 的书放到最后面;
3,p q 表示把编号为 p 的书放到编号为 q 的书的后面;
1、2、3 分别代表整理操作的种类,p、q 表示书的编号,他们之间由空格分隔;已知在整理之前,所有书从 1 开始依次编号排放。
输入描述 Input Description
共 m+1 行。第一行有两个由空格分隔的正整数 n 和 m,分别表示 n 本书和 m 次整理操作,接下来 m 行,每行有 2 个或 3 个由空格分隔的正整数,对应上述三种整理操作。
输出描述 Output Description
共 1 行,经过整理后的书本顺序,书本间用空格隔开。
样例输入 Sample Input
10 4
1 3
2 4
3 3 6
3 1 5
样例输出 Sample Output
2 5 1 6 3 7 8 9 10 4
数据范围及提示 Data Size & Hint
数据范围:1≤n,m≤100000
本题不能使用模拟写法,会超时,得用模拟链表才不会超时
满分代码来了!!!
#include<iostream>
using namespace std;
int n,m,t,p,q;
int r[100005];//存第i个结点的后继地址
int l[100005];//存第i个结点的前驱地址
int main(){
cin>>n>>m;
r[0]=1;
for(int i=1;i<=n;i++){
r[i]=i+1;//第i个结点的后继地址
l[i]=i-1;//第i个结点的前驱地址
}
l[n+1]=n;
while(m--){
cin>>t>>p;
if(t==1){//表示把编号为p的书放到最前面;
r[l[p]]=r[p];
l[r[p]]=l[p];//删除结点p
l[p]=0;
r[p]=r[0];//插入结点p
r[l[p]]=p;
l[r[p]]=p;//连接结点p
}else if(t==2){
r[l[p]]=r[p];
l[r[p]]=l[p];//删除结点p
l[p]=l[n+1];
r[p]=n+1;//插入结点p
r[l[p]]=p;
l[r[p]]=p;//连接结点p
}else{
cin>>q;
if(p==q) continue;
r[l[p]]=r[p];
l[r[p]]=l[p];//删除结点p
l[p]=q;
r[p]=r[q];//插入结点p
r[l[p]]=p;
l[r[p]]=p;//连接结点p
}
}
int idx=r[0];
while(idx!=n+1){
cout<<idx<<" ";
idx=r[idx];
}
return 0;
}