分析转自:http://www.haogongju.net/art/1647260
这题比较容易想到的做法是splay,但是splay写起来比较麻烦而且每次操作都有LogN的复杂度,双向链表也是可以实现的,但实践起来比较麻烦,尤其是翻转操作。。。
可以发现每次L或者R都是移动一位的,我们可以用更简单的数据结构来实现,用两个栈分别存L左边和R右边的数据,L和R中间的数据使用一个双端队列来保存,因为涉及到翻转操作,要用一个dir来表示当前的双端队列哪边是头哪边是尾。。。
对于题目中给出的七种操作,都可以在O(1)的复杂度内实现,为了描述方便,左栈代表L左边数的栈,右栈代表R右边数的栈。
1,MoveLeft L/R 左移左指针就是把左栈中栈顶的数弹到双端队列头部,左移右指针就是把队列尾部的元素放到右栈中。
2,MoveRight L/R 右移左指针就是把队列头部元素放到左栈中,右移右指针就是把右栈顶元素弹到双端队列尾部。
3,Insert L X 插入到队列头。
4,Insert R X 插入到队列尾。
5,Delete L 删除队列头元素。
6,Delete R 删除队列尾元素。
7,Reverse dir^=1。
Code1(用数组模拟双端队列,栈):
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define pb push_back
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000005;
int cas,n,m,x[maxn],l,r;
int dq[maxn*2],head,tail;
int stkl[maxn],stkr[maxn];
char s1[20],s2[20];
int dir,topl,topr;
void init(){
topl=topr=dir=0;
head=maxn; tail=maxn-1;
for(int i=1;i<l;i++) stkl[++topl]=x[i];
for(int i=l;i<=r;i++) dq[++tail]=x[i];
for(int i=n;i>r;i--) stkr[++topr]=x[i];
}
void MoveLR(char op,char c){
if(op=='L'&&c=='L'){
if(!dir) dq[--head]=stkl[topl--];
else dq[++tail]=stkl[topl--];
}
else if(op=='R'&&c=='L'){
if(!dir) stkl[++topl]=dq[head++];
else stkl[++topl]=dq[tail--];
}
else if(op=='L'&&c=='R'){
if(!dir) stkr[++topr]=dq[tail--];
else stkr[++topr]=dq[head++];
}
else {
if(!dir) dq[++tail]=stkr[topr--];
else dq[--head]=stkr[topr--];
}
}
void Insert(char c){
int num;
scanf("%d",&num);
if(c=='L') {
if(!dir) dq[--head]=num;
else dq[++tail]=num;
}
else {
if(!dir) dq[++tail]=num;
else dq[--head]=num;
}
}
void Delete(char c){
if(c=='L'){
if(!dir) head++;
else tail--;
}
else {
if(!dir) tail--;
else head++;
}
}
void Reverse(){
dir^=1;
}
void print(){
int cnt=0;
for(int i=1;i<=topl;i++) x[++cnt]=stkl[i];
if(!dir) for(int i=head;i<=tail;i++) x[++cnt]=dq[i];
else for(int i=tail;i>=head;i--) x[++cnt]=dq[i];
for(int i=topr;i>0;i--) x[++cnt]=stkr[i];
for(int i=1;i<cnt;i++) printf("%d ",x[i]); printf("%d\n",x[cnt]);
}
int main()
{
scanf("%d",&cas);
while(cas--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&x[i]);
scanf("%d %d %d",&l,&r,&m);
init();
while(m--){
scanf("%s",s1);
if(s1[0]!='R') scanf("%s",s2);
switch(s1[0]){
case 'M':MoveLR(s1[4],s2[0]);break;
case 'I':Insert(s2[0]);break;
case 'D':Delete(s2[0]);break;
case 'R':Reverse();break;
}
}
print();
}
return 0;
}
Code2(用C++ STL deque实现):
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define pb push_back
#define pf push_front
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000005;
deque<int>a,b,c;
char s1[20],s2[20];
int num[maxn],n,m,dir,cas,l,r;
void init(){
dir=0;
a.clear(); b.clear(); c.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
scanf("%d %d %d",&l,&r,&m);
for(int i=1;i<l;i++) a.pb(num[i]);
for(int i=l;i<=r;i++) b.pb(num[i]);
for(int i=r+1;i<=n;i++) c.pb(num[i]);
}
void MoveLR(char op,char ch){
if(op=='L'&&ch=='L'){
if(!dir) b.pf(*a.rbegin());
else b.pb(*a.rbegin());
a.pop_back();
}
else if(op=='R'&&ch=='L'){
if(!dir) a.pb(*b.begin()),b.pop_front();
else a.pb(*b.rbegin()),b.pop_back();
}
else if(op=='L'&&ch=='R'){
if(!dir) c.pf(*b.rbegin()),b.pop_back();
else c.pf(*b.begin()),b.pop_front();
}
else {
if(!dir) b.pb(*c.begin());
else b.pf(*c.begin());
c.pop_front();
}
}
void Insert(char ch){
int v;
scanf("%d",&v);
if(ch=='L') {
if(!dir) b.pf(v);
else b.pb(v);
}
else if(ch=='R'){
if(!dir) b.pb(v);
else b.pf(v);
}
}
void Delete(char ch){
if(ch=='L'){
if(!dir) b.pop_front();
else b.pop_back();
}
else {
if(!dir) b.pop_back();
else b.pop_front();
}
}
void Reverse(){
dir^=1;
}
void print(){
int cnt=0;
deque<int>::iterator it;
deque<int>::reverse_iterator rit;
for(it=a.begin();it!=a.end();it++) num[++cnt]=*it;
if(!dir) for(it=b.begin();it!=b.end();it++) num[++cnt]=*it;
else for(rit=b.rbegin();rit!=b.rend();rit++) num[++cnt]=*rit;
for(it=c.begin();it!=c.end();it++) num[++cnt]=*it;
for(int i=1;i<cnt;i++) printf("%d ",num[i]); printf("%d\n",num[cnt]);
}
int main()
{
scanf("%d",&cas);
while(cas--){
init();
while(m--){
scanf("%s",s1);
if(s1[0]!='R') scanf("%s",s2);
switch(s1[0]){
case 'M':MoveLR(s1[4],s2[0]);break;
case 'I':Insert(s2[0]);break;
case 'D':Delete(s2[0]);break;
case 'R':Reverse();break;
}
}
print();
}
return 0;
}