HDU5929(双端队列+与非的性质+模拟找规律)

 最新学习双端队列的用法。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5+10;
int num[maxn*2];
int l,r,t,cas;
deque<int>que;
int flag;
char str[15];

void init()
{
    l = maxn;
    r = maxn-1;
    flag = 1;
    que.clear();
}
void push(int x)
{
    if(flag)
    {
        num[++r] = x;
        if(x == 0)
            que.push_back(r);
    }
    else
    {
        num[--l] = x;
        if(x == 0)
            que.push_front(l);
    }
}
void pop()
{
    if(flag)
    {
        if(num[r] == 0)
            que.pop_back();
        r--;
    }
    else
    {
        if(num[l] == 0)
            que.pop_front();
        l++;
    }
}
void re()
{
    flag^=1;
}
void nand()
{
    int cnt,ans;
    if(l>r)
    {
        printf("Invalid.\n");
        return;
    }
    if(que.empty())
    {
        cnt = r-l+1;
    }
    else
    {
        if(flag)
        {
            ans = que.front();
            if(ans == r)
            {
                cnt = ans - l;
            }
            else
            {
                cnt = ans - l + 1;
            }
        }
        else
        {
            ans = que.back();
            if(ans == l)
            {
                cnt = r - ans;
            }
            else
            {
                cnt = r - ans + 1;
            }
        }
    }
    printf("%d\n",cnt&1);
    return;
}
void output()
{
    deque<int>::iterator pos = que.begin();
    for(; pos != que.end(); pos++)
        printf("%d ",*pos);
    printf("\n");
    for(int i = l; i <= r; ++i)
        printf("%d ",num[i]);
    printf("\n");
}
int main()
{
    scanf("%d",&t);
    cas = 1;
    int m,x;

    while(t--)
    {
        init();
        scanf("%d",&m);

        printf("Case #%d:\n",cas++);
        while(m--)
        {
            scanf("%s",str);
            if(str[0] == 'P')
            {
                if(str[1] == 'O')
                {
                    pop();
                }
                else
                {
                    scanf("%d",&x);
                    push(x);
                }
            }
            else if(str[0] == 'R')
            {
                re();
            }
            else
            {
                nand();
            }
            //output();
        }
    }
    return 0;
}

附上双端队列的学习地址:https://www.cnblogs.com/grhyxzc/p/5074061.html

【一】想要提一下的知识点是双端队列的取两端元素的函数是:

int x = que.back();//取尾部元素

int y = que.front();//取头部元素

//其实返回的是引用,而引用正是变量的别名

【二】与非的性质

【A】0与非x和x与非0的结果都是1

【B】多个1与非的结果是(1的数量&1)

【C】根据上两个知识点可以得到解题思路:我们只要找到离栈底最近的0的位置和栈底的位置就能计算出中间有多少1

从而根据【B】快速计算出结果

本题中由于栈顶和栈底可以相互转化,造成栈底的位置不固定,因此需要记录所有0的位置(利用一个双端队列)

从而方便的找出来里栈顶或者栈底最近的0的位置,从而求解

猜你喜欢

转载自blog.csdn.net/qq_41658955/article/details/87863225