http://acm.hdu.edu.cn/showproblem.php?pid=5929
题目大意:
栈的四个操作
PUSH 进栈 进栈元素只有0/1
POP 出栈
REVERSE 将栈内元素逆置
QUERY 将栈内所有元素逐个与非并输出最后结果
分析:
数组模拟这个栈 逆置的时候不需要真正将元素逆置只需要将栈顶指针和栈底指针交换一下就行 然后就是规律了 可以发现最终结果与据栈底最近的0相关 分别讨论各种情况详见注释 需要注意一下栈顶指针指栈顶元素的下一个位置
AC代码:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
int Stack[600500];
int main (){
int t;
// freopen("data","r",stdin);
scanf ("%d",&t);
int cc=1;
while (t--){
set<int> ss;// 存储栈中0的位置
ss.clear();
int n;
scanf ("%d",&n);
char str[10];
int start,end;// 栈底、栈顶
start=end=300000;// 栈初始栈底与栈顶指针位置 由于要交换栈底和栈顶指针所以位置置中
int flag=0;// 0时左侧为栈底 1时右侧为栈底
printf ("Case #%d:\n",cc++);
while (n--){
scanf ("%s",str);
if (strcmp(str,"PUSH")==0){
int temp;
scanf ("%d",&temp);
if (flag){
if (temp==0) ss.insert(end);
Stack[end--]==temp;
}
else {
if (temp==0) ss.insert(end);
Stack[end++]=temp;
}
}
else if (strcmp(str,"POP")==0){
if (flag) {
end++;
if (Stack[end]==0) ss.erase(end);
}
else {
end--;
if (Stack[end]==0) ss.erase(end);
}
}
else if (strcmp(str,"REVERSE")==0){
flag^=1;
swap(start,end);
if (flag){
start--; end--;
}
else{
start++; end++;
}
}
else if (strcmp(str,"QUERY")==0){
if (start==end){// 栈空
printf ("Invalid.\n");
continue;
}
if (abs(end-start)==1){// 栈中只有一个元素
printf ("%d\n",Stack[start]);
continue;
}
int sum;
if (flag){
if (!ss.empty()) sum=start-*ss.rbegin();// 栈中有0 找到距栈底最近的0与栈底之间有多少个1
else sum=abs(end-start);// 栈中没有0 统计1的个数
if (!ss.empty()){// 栈中有0
if (*ss.rbegin()==(end+1)) printf ("%d\n",sum%2);// 若距栈底最近的0为栈顶元素则奇数1为1偶数1为0
else printf ("%d\n",(sum%2)^1);// 否则相反
}
else printf ("%d\n",sum%2);// 栈中没有0 奇数个1为1偶数个1为0
}
else{
if (!ss.empty()) sum=*ss.begin()-start;
else sum=abs(end-start);
if (!ss.empty()){
if (*ss.begin()==(end-1)) printf ("%d\n",sum%2);
else printf ("%d\n",(sum%2)^1);
}
else printf ("%d\n",sum%2);
}
}
}
}
return 0;
}