Basic Data Structure(弱校联盟十一专场)

本文解析了一道涉及栈操作及与非逻辑运算的算法题。通过详细阐述解题思路,介绍了如何利用栈实现特定操作,并根据这些操作确定最终答案的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}

体会:找到这道题的考点和陷进即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值