第一次写自己的题解希望大家多多包含。
正题:附上题目链接http://acm.csu.edu.cn/csuoj/contest/problem?cid=2157&pid=V
题目讲的是要实现对一个有序序列进行三种操作,并输出操作后的序列。
1.1 u 表示将u置于序列首
2.2 u 表示将u置于序列尾
3.3 u v 表示将u置于v后面
看到这种问题,这些操作,我当然想到的是链表
第一个思路:用了双向链表(头指针head,尾指针tail),但是提交time limit exceed.
仔细考虑之后发现由于后台给的测试数据较大,在用这种传统的指针双向链表时,由于每次操作多了一个“遍历查找”,所以超时是难以避免的。
换一个思路:用两个数组来模拟双向链表,lef[i]表示i左边的数据,righ[i]表示i右边的数据。这样一来,每次都能在O(1)的时间内找到源操作数,快速的多。而实现两个数的连接,可以用以下函数
void link(int L,int R)
{
righ[L]=R;
lef[R]=L;
}
直接附上源代码(C++)
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=300000+5;
/*这题中的用两个数组模拟双向链表的思想与操作尤为金桥
特别是对于头指针、尾指针的设置*/
int lef[maxn];
int righ[maxn];
void link(int L,int R);
int main()
{
int T;
int n,m;
int order,a,b;
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=n+1;i++)
{
lef[i]=i-1;
righ[i]=(i+1)%(n+2);
}
lef[0]=n+1;
righ[0]=1;
righ[n+1]=0;
while(m--)
{
cin>>order;
if(order==1)
{
cin>>a;
link(lef[a],righ[a]);//置顶前奏
//置顶的操作
link(a,righ[0]);
link(0,a);
}
else if(order==2)
{
cin>>a;
link(lef[a],righ[a]);//至尾前奏
//至尾操作
//注意先后顺序
link(lef[n+1],a);
link(a,n+1);
}
else if(order==3)
{
cin>>a>>b;
link(lef[a],righ[a]);
link(a,righ[b]);
link(b,a);
}
}
int b=0;
for(int i=1;i<n;i++)
{
b=righ[b];
cout<<b<<" ";
}
b=righ[b];
cout<<b<<endl;
}
return 0;
}
void link(int L,int R)
{
righ[L]=R;
lef[R]=L;
}
另外解释一下为什么两个数组名没用left,right.因为本人的编译器的原因,似乎是ios_base::right已经存在关键词,具体也不懂。
哪位能解释一下,在下小白感激不尽!!