HDU 4286 Data Handler [栈,双端队列]

12 篇文章 0 订阅
9 篇文章 0 订阅

分析转自: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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值