D - Dequeue SGU - 271

1.题目
SGU - 271
There is a pile of N books on the table. Two types of operations are performed over this pile:

  • a book is added to the top of the pile,
  • top K books are rotated. If there are less than K books on the table, the whole pile is rotated.
    First operation is denoted as ADD(S) where S is the name of the book, and the second operations is denoted as ROTATE.
    The maximum number of books is no more than 40000. All book names are non-empty sequences of no more than 3 capital Latin letters. The names of the books can be non-unique.
    Input
    The first line of input file contains 3 integer numbers N, M, K (0 <= N <= 40000; 0 <= M <= 100000; 0 <= K <= 40000). The following N lines are the names of the books in the pile before performing any operations. The book names are given in order from top book to bottom. Each of the following M lines contains the operation description.
    Output
    Output the sequence of books names in the pile after performing all operations. First line corresponds to the top book.
    Sample test(s)
    Input
    2 3 2
    A
    B
    ADD©
    ROTATE
    ADD(D)
    Output
    D
    A
    C
    B
    Author: Michael R. Mirzayanov
    Resource: ACM ICPC 2004-2005, NEERC, Southern Subregional Contest
    Date: Saratov, October 7, 2004

2.题目大意
一开始桌子上从上到下放着N本书,有M组操作:
1.将前K本书翻转。
2.在头上加一本书。最后输出书的顺序。

3.解题思路
把前k本书在双端队列Q中进行维护,后k本书在另外一个队列q中放置。
当是ADD操作时,根据此时翻转的情况,看把书是加入底部还是顶部。
当是ROTATE操作时,记录翻转的次数。其中根据翻转的次数来决定ADD
的操作和最后的输出,时间效率会比较好,每一个ROTATE操作都进行
倒置操作的模拟的话,显然是不符合时间限制的。

4.双端队列

 #include <queue>//必要的头文件
 deque<string>Q; //定义一个双端队列Q
 Q.push_back(e);//将某元素e放进Q的底部
 Q.push_front(s);//将某元素s放进Q的顶部
 Q.size();//双端队列中元素的个数
 Q.pop_front();//顶部元素释放
 Q.pop_back();//底部元素释放 

AC代码

#include <iostream>
#include <queue>
#include<string>
#include<cstdio>
using namespace std;

int main()
{
    int n, m, k, a =0; cin>>n>>m>>k;
    //双端队列,两端都可以进入
    deque<string>Q; //前k本需要翻转的书
    deque<string>q;//之后不用翻转的书
    for( int i = 1; i <= n; i++)
    {
       string e;
       cin>>e;
        if(i <= k) Q.push_back(e); //Q内先放进去的是会被翻转的
        else q.push_back(e); //q内放进去的是不会被翻转的
    }
    for(int i = 1; i <= m; i++)
    {
        char ch[20];
        scanf("%s",ch);
        if(ch[0] == 'A') //说明是在顶部加了一本书
        {
            int  t = 0;//因为书的名字可能是A,AA,AAA
            if(ch[5] == ')' ) t = 4; //类似A
            else if(ch[6] == ')' ) t = 5;//类似AA
            else t = 6;//类似AAA
            string  s;
            for(int j =4; j<=t; j++ )
                s+=ch[j];//把这本书的名字放在string的s中
            if(a%2 == 0) Q.push_front(s); //第一次进来从头上进,翻转两次后同理
            else Q.push_back(s); // 翻转了一次后从尾部进
            if(Q.size() > k)//如果Q中的书已经大于k值了,就说明当前最下面的那本书要拿开
            {
                if(a % 2 == 0) //第一次,或者翻转两次了之后,是最开始进来的状态
                {
                    q.push_front(Q.back());//把Q中的最后一本书放进q中
                    Q.pop_back();//把这本书从Q中移开
                }
                else//翻转了一次之后,相当于最初状态的倒置
                {
                    q.push_front(Q.front());//此时原本在顶部的书在最底部,把它放进q中
                    Q.pop_front();//移开
                }
            }
        }
        if(ch[0] == 'R')
        {
            a +=1;
        }
    }
    if(a % 2 == 0 ) //说明是跟刚初始时放置状态一样
    { //可以从头开始释放
        while(Q.size() > 0)
        {
            cout<<Q.front()<< endl;
            Q.pop_front();
        }
    }
    else//说明是初始状态的倒置
    {
        while(Q.size()>0)//从尾部开始释放
        {
            cout<<Q.back()<<endl;
            Q.pop_back();
        }
    }
    while(q.size()>0)//如果在这个队列中还有,那么从头开始释放就是。
    {
        cout<<q.front()<<endl;
        q.pop_front();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值