[找规律+模拟+数组或双端队列]hdu 5929 (2016CCPC东北地区大学生程序设计竞赛)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5929

/*
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5929
题意:给一个stack 它包括4种操作
         PUSH x 在栈顶插入一个数x x只能是0或1
         POP 弹出栈顶元素
         REVERSE 将栈顶和栈底反向
         QUERY 询问按照出栈顺序求所有数的 NAND(与非)值
分析: 找规律+模拟+数组或双端队列
         1.找规律
         与非
         0 0 0
         0 1 0
         1 0 0
         1 1 1
         可以发现 无论多少个0 1与非 如果最后一位为0 则结果必为1
         所以询问的时候只要找到当前情况下离栈底最近的0 数0后面有几个1 即可
         如果只有或没有0或只有1个0(0前面一个数都没有) 
         则 0后面奇数个1 的NAND 为1
                    偶数个1 的NAND 为0
         如果有多个0 或0前面有数
         则0后面奇数个1 的NAND 为0
                   偶数个1 的NAND 为1
         2.模拟+数组
         开2*MAXN的数组模拟双端栈PUSH x和POP  用一个bool类型 表示REVERSE 
         并在插入时记录0的位置 
         3.模拟+双端队列
         3.1 和数组类似的 只不过用队列模拟
         3.2 还有一种方法 双端队列存 0后面有多少个1(无论正反插入都要按正的顺序算)
                               正 开一个int类型 topone 记录 0后面有多少个1 出现0的时候将topone存入队列
                               反 队列不空 其最后一个元素的值+1 
                                       为空 等于正着为空 topone++即可
*/
///3.2 ac 代码
#include<algorithm>
#include<limits.h>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<set>
using namespace std;
const int MAXN = 200005;
deque <int>a;//双端队列 记录0的前面(无论正反都是按正着算的前面)有几个1
bool flag=1;//=1正序 =0倒序
int topone=0;//正着从上一个0算起有几个1
///int zero=0;//队列中0的个数 可用 a.size()代替
void init(){
    a.clear();//清空队列
    flag=1;
    topone=0;
    ///zero=0;
}
int main(){
    int t;
    int n;
    char rule[10];
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        init();
        scanf("%d",&n);
        printf("Case #%d:\n",cas);
        for(int cnt=1;cnt<=n;cnt++){
            if(cnt==1)getchar();
            gets(rule);
            if(rule[1]=='O'){//pop
                    if(a.empty()){
                        topone--;
                    }
                    else if(flag){//正
                        if(topone!=0)//有1
                            topone--;
                        else{//zero--;
                            int tempnum=a.front();
                            a.pop_front();
                            topone=tempnum;
                        }
                    }
                    else{//负
                       int tempnum=a.back();
                       if(tempnum>0){//有1
                            a.pop_back();
                            a.push_back(tempnum-1);
                       }
                       else//zero--;
                            a.pop_back();
                    }
            }
            else if(rule[0]=='P'){//push x
                int temp=rule[5]-'0';
                if(temp==1){//==1 下一个0前面的1++
                   if(flag)//正
                       topone++;
                    else{//负
                       if(!a.empty()){
                            int tempnum=a.back()+1;
                            a.pop_back();
                            a.push_back(tempnum);
                       }
                       else
                            topone++;
                    }
                }
                else{//zero++;
                    if(flag){//正
                       a.push_front(topone);
                       topone=0;
                    }
                    else//负
                       a.push_back(0);
                }
            }
            else if(rule[0]=='R'){//reverse
                if(flag)flag=0;
                else flag=1;
            }
            else if(rule[0]=='Q'){//query
                if(a.empty()){//没有0
                    if(topone==0)//没有数字
                        printf("Invalid.\n");
                    else
                        printf("%d\n",topone%2==0?0:1);
                }
                else{
                    if(flag){
                        int botone=a.back();
                        if(a.size()==1&&topone==0)printf("%d\n",botone%2==0?0:1);
                        else printf("%d\n",botone%2==0?1:0);
                    }
                    else{
                        if(a.size()==1&&a.back()==0)printf("%d\n",topone%2==0?0:1);
                        else printf("%d\n",topone%2==0?1:0);
                    }
                }
            }
        }
    }
    return 0;
}
///2 ac 代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;

typedef long long llong;
const int maxn = 400000 + 100;
const int half = 200000;
int zero[maxn];
int a[maxn];

int main()
{
    int T;
    scanf("%d", &T);
    for (int t=1; t<=T; t++)
    {
        //memset(zero, -1, sizeof(zero));

        int n;
        scanf("%d", &n);
        printf("Case #%d:\n", t);

        char op[10];
        int x;
        int rev = 0;
        int head = 1 + half;       //存整个数列的开始
        int tail = 0 + half;       //表示现在数的结束

        int st = 1 + half;         //存0的开始
        int en = 0 + half;         //存0的结束
        int one;

        while (n--)
        {
            scanf("%s", op);
            if (op[0] == 'R')
            {
                rev = !rev;
            }
            else if (op[0] == 'Q')      //query
            {
                //for (int i=head; i<=tail; i++)
                //    printf("a[%d]=%d\n", i, a[i]);
                //printf("st=%d en=%d\n", st, en);

                if (head > tail)        //栈里没有元素
                    puts("Invalid.");
                else if (st > en)            //没有0
                {
                    one = (tail - head + 1);
                    //printf("one=%d\n", one);
                    if (one & 1)
                        puts("1");
                    else
                        puts("0");
                }
                else if (!rev)               //没有反转
                {
                    one = zero[st] - head;     //看最后的头部
                    int f = 1;
                    if (zero[st] == tail)
                        f = 0;

                    if (f)                      //0->1
                        one++;

                    if (one & 1)
                        puts("1");
                    else
                        puts("0");
                }
                else if (rev)
                {
                    one = tail - zero[en];    //1的个数
                    int f = 1;                //0前面有数
                    if (head == zero[en])
                        f = 0;                  //0前面没有数了
                    if (f)                      //0前面有数(0->1)
                        one++;

                    if (one & 1)
                        puts("1");
                    else
                        puts("0");


                }
            }
            else if (op[1] == 'O')      //pop
            {
                if (!rev)                //从tail pop
                {
                    if (tail == zero[en])//这是一个0
                    {
                        --en;
                    }
                    --tail;
                }
                else                    //从head出来
                {
                    if (head == zero[st])
                    {
                        ++st;
                    }
                    ++head;
                }
            }
            else if (op[1] == 'U')      //push
            {
                scanf("%d", &x);
                if (!rev)               //从tail进去
                {
                    ++tail;             //存坐标
                    a[tail] = x;
                    if (x == 0)         //这是一个0
                    {
                        ++en;
                        zero[en] = tail;
                    }

                }
                else                    //从head进去
                {
                    --head;
                    a[head] = x;
                    if (x == 0)
                    {
                        --st;
                        zero[st] = head;
                    }
                }
            }
        }


    }
    return 0;
}
posted @ 2017-09-22 23:06  py准备学python  阅读(193)  评论(0)    收藏  举报