Question:题目详情(http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1008&cid=729)
题目大意:有一个栈有四个操作∙ PUSH x (x must be 0 or 1) ∙ POP(弹出栈顶元素) . REVERSE( 置逆) ∙ QUERY(根据与非的出最终答案) 与非:0~1->1;0~0->1;1~0->1;1~1->0
解题思路:只需要找到最接近栈底一个0即可,因为无论前面的一串为任何数与0或非都为1(当然得考虑最接近栈底的0前面到底有没有元素,情况是不同的),最接近栈底的0与栈底之间有几个1,最终1的个数为偶数时,输出0,为奇数时输出1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int a[500000],n,T,s,e,ncase; //用一个500000的数组从中间进行
char str[20];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("Case #%d:\n",++ncase);
int h1=-1,h2=-1,flag=0,flag2=0; //flag标记是否有最接近栈底的0,flag2标记是否置逆,h1保存最接近栈底的0,h2表示最接近栈顶的0(因为置逆后会成为最接近栈底的0
s=250000;e=249999; //s表示栈顶,e便是栈底
while(n--)
{
scanf("%s",str);
if(str[0]=='P')
{
if(str[1]=='U') //执行push
{
int tp;
scanf("%d",&tp);
if(tp==0)
{
if(flag==0) //判断是不是第一个出现的0
{flag=1;h1=s;}
h2=s;
}
if(flag2) //如果置逆s<e所以push应该s--
a[s--]=tp;
else a[s++]=tp;
}
}
if(str[1]=='O') //执行pop
{
if(abs(s-e)!=1) //判断这是不是空栈
{
if(flag2) //如果置逆刚好相反
{
s++;
if(a[s]==0)
{
if(h1==s)
{
h1=h2=-1;
flag=0;
}
else
{
int x=s+1;
while(a[x]!=0)
x++;
h2=x;
}
}
}
else
{
s--;
if(a[s]==0)
{
if(h1==s) //判断弹出的是不是最接近的栈底的0
{
h1=h2=-1;
flag=0;
}
else
{
int x=s-1; //如果不是最接近栈底的0,找到下一个最接近栈底的那个0
while(a[x]!=0)
x--;
h2=x;
}
}
}
}
}
if(str[0]=='R')
{
flag2^=1; //标记与1异或
swap(h1,h2); //交换最接近栈顶的0和最接近栈底的0
swap(s,e); //交换栈底和栈顶
}
if(str[0]=='Q')
{
// cout<<h1<<h2<<endl;
//cout<<s<<" "<<e<<" "<<flag2<<endl;
if(abs(s-e)==1) //这是一个空栈
printf("Invalid.\n");
else if(abs(s-e)==2) //如果栈中只有一个元素,输出这个元素
printf("%d\n",a[max(s,e)-1]);
else if(h1==-1) //如果栈中没有0
{
if(((int)abs(s-e)-1)%2) //奇数个1输出1
printf("1\n");
else printf("0\n"); //偶数个1输出0
}
else if(((int)abs(h1-e)%2==0&&abs(s-h1)!=1)||((int)abs(h1-e)%2==1&&(int)abs(s-h1)==1)) //如果最接近栈底的0(算上)和栈底之间的1的个数为偶数并且0前面有元素或者1的个数为奇数并且0前面无元素输出0
printf("0\n");
else if(((int)abs(h1-e)%2&&abs(s-h1)!=1)||((int)abs(h1-e)%2==0&&(int)abs(s-h1)==1))//恰好与前面的相反
printf("1\n");
}
}
}
return 0;
}
体会:找到这道题的考点和陷进即可