最新学习双端队列的用法。
#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的位置,从而求解