[找规律+模拟+数组或双端队列]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;
}

浙公网安备 33010602011771号