此文章可以使用目录功能哟↑(点击上方[+])
HDU 5929 Basic Data Structure
Accept: 0 Submit: 0
Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
Mr. Frog learned a basic data structure recently, which is called stack.There are some basic operations of stack:
? PUSH x: put x on the top of the stack, x must be 0 or 1.
? POP: throw the element which is on the top of the stack.
Since it is too simple for Mr. Frog, a famous mathematician who can prove "Five points coexist with a circle" easily, he comes up with some exciting operations:
?REVERSE: Just reverse the stack, the bottom element becomes the top element of the stack, and the element just above the bottom element becomes the element just below the top elements... and so on.
?QUERY: Print the value which is obtained with such way: Take the element from top to bottom, then doNAND operation one by one from left to right, i.e. If is corresponding to the element of the Stack from top to the bottom, value=. Note that the Stackwill not change after QUERY operation. Specially, if the Stack is empty now,you need to print ”Invalid.”(without quotes).
By the way, NAND is a basic binary operation:
? 0 nand 0 = 1
? 0 nand 1 = 1
? 1 nand 0 = 1
? 1 nand 1 = 0
Because Mr. Frog needs to do some tiny contributions now, you should help him finish this data structure: print the answer to each QUERY, or tell him that is invalid.
Input
The first line contains only one integer T (T≤20), which indicates the number of test cases.
For each test case, the first line contains only one integers N (2≤N≤200000), indicating the number of operations.
In the following N lines, the i-th line contains one of these operations below:
? PUSH x (x must be 0 or 1)
? POP
? REVERSE
? QUERY
It is guaranteed that the current stack will not be empty while doing POP operation.
Output
For each test case, first output one line "Case #x:w, where x is the case number (starting from 1). Then several lines follow, i-th line contains an integer indicating the answer to the i-th QUERY operation. Specially, if the i-th QUERY is invalid, just print "Invalid."(without quotes). (Please see the sample for more details.)
Sample Input
8
PUSH 1
QUERY
PUSH 0
REVERSE
QUERY
POP
POP
QUERY
3
PUSH 0
REVERSE
QUERY
Sample Output
1
1
Invalid.
Case #2:
0
Hint
In the first sample: during the first query, the stack contains only one element 1, so the
answer is 1. then in the second query, the stack contains 0, l
(from bottom to top), so the answer to the second is also 1. In the third query, there is no
element in the stack, so you should output Invalid.
Problem Idea
解题思路:
【题意】
众所周知,数据结构中的栈具有PUSH x(此题的x限定为0 or 1)和POP两种操作
现在增加两种操作:REVERSE、QUERY
REVERSE:将栈内元素倒置,即本身从栈顶到栈底的数是a1,a2,...,an,经此操作后,从栈顶到栈底的数为an,...,a2,a1
QUERY:输出从栈顶到栈底元素(a1,a2,...,an)的与非值a1 nand a2 nand ... nand an
【类型】
模拟,deque
【分析】
数据结构模拟题,用deque就可以了(deque:双端队列,可以对队列两端进行操作,REVERSE可以看成是对队列的两端进行操作,只需借用一个bool型变量is_top来标记双端队列的哪一头模拟栈顶即可)
但解决问题的关键还是在于发现与非运算的规律,这样,才能将每次查询时O(n)时间复杂度的计算变为O(1)
(1):0和任何数与非均为1(这个任何数不仅仅指0,1,也指任意一个01序列)
(2):奇数个1与非得到1,偶数个1与非得到0
那么,我们可以知道:我们需要统计的是连续的0或1的个数(用pair(x,y)表示,并放入deque中)
x代表0或者1,y代表当前的x连续有多少个
那么,如何来计算呢?
特殊情况:deque中就一个元素:根据规律算一下
否则:
我们需要判断一下:如果栈顶元素是0,那么答案是1(0和任何数与非得到1)
如果栈顶元素是1,那我们知道,第二个元素必定是0
如果连续的0只有1个而且deque中只有两个元素那么这个0元素是个特殊情况
否则:
因为0与任何数与非均为1
相当于栈顶元素是1的连续个数多了一个,用O(1)的复杂度就可以解决了
为了进一步的理解,本人会对代码中的每种情况加以说明
其中⑴~⑸是PUSH x操作,⑹⑺是POP操作,⑻是REVERSE操作,⑼~⒇+⑶是QUERY操作
⑴往空栈中压入一个数
因为此时deque中是空的,所以从哪一头插入这个数的效果都是一样的,故d.push_back(make_pair(x,1))和d.push_front(make_pair(x,1))均可
⑵往栈顶压入一个数(队尾为栈顶,且栈顶元素与压入的数不一致)
由于我们是将连续个1或连续个0当成一个整体存放的,此时放入的数与栈顶元素不同,意味着连续在这里截断了,故需另外压入一个,即d.push_back(make_pair(x,1))
⑶往栈顶压入一个数(队尾为栈顶,且栈顶元素与压入的数相同)
相同意味着还是一个连续段,那我们只要在原有基础上+1,就可以表示
同理,后续操作类似,要是有需要博主额外讲解的,可在此题留下评论
【时间复杂度&&优化】
O(N)
题目链接→HDU 5929 Basic Data Structure
Source Code
/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 10;
const int M = 100005;
const int inf = 1000000007;
const int mod = 1000000007;
char s[N];
deque< pair<int,int> > d;
deque< pair<int,int> >::iterator it;
deque< pair<int,int> >::reverse_iterator rit;
int main()
{int t,n,x,p=1;bool is_top;pair<int,int> k;scanf("%d",&t);while(t--){d.clear();is_top=true;//默认队尾是栈顶scanf("%d",&n);printf("Case #%d:\n",p++);while(n--){scanf("%s",s);if(s[2]=='S')//PUSH{scanf("%d",&x);if(d.empty())//⑴d.push_back(make_pair(x,1));else{if(is_top){k=d.back();if(k.first!=x)//⑵d.push_back(make_pair(x,1));else//⑶{d.pop_back();k.second++;d.push_back(k);}}else{k=d.front();if(k.first!=x)//⑷d.push_front(make_pair(x,1));else//⑸{d.pop_front();k.second++;d.push_front(k);}}}}else if(s[2]=='P')//POP{if(is_top)//⑹{k=d.back();d.pop_back();k.second--;if(k.second)d.push_back(k);}else//⑺{k=d.front();d.pop_front();k.second--;if(k.second)d.push_front(k);}}else if(s[2]=='V')//REVERSEis_top=!is_top;//⑻else//QUERY{if(d.empty())//⑼puts("Invalid.");else if(d.size()==1){k=d.back();if(k.first){if(k.second%2)//⑽puts("1");else//⑾puts("0");}else{if(k.second!=1)//⑿puts("1");else//⒀puts("0");}}else{if(is_top){k=d.front();if(!k.first)//⒁puts("1");else{it=d.begin();it++;if(d.size()==2&&(*it).second==1){if(k.second%2)//⒂puts("1");else//⒃puts("0");}else{if(k.second%2)//⒄puts("0");else//⒅puts("1");}}}else{k=d.back();if(!k.first)//⒆puts("1");else{rit=d.rbegin();rit++;if(d.size()==2&&(*rit).second==1){if(k.second%2)//⒇puts("1");else//⒇+⑴puts("0");}else{if(k.second%2)//⒇+⑵puts("0");else//⒇+⑶puts("1");}}}}}}}return 0;
}
菜鸟成长记