题意:有两个栈A和B,有3种操作:push,pop,merge。前两种都是栈的操作,最后一种表示的是如果“merge A B”,那么把B中的元素全部放到A中,且满足先入后出的栈原则。
分析:显然,我们给每一个节点配备一个时间戳即可。我一开始的思路是直接开两个优先队列进行直接模拟,merge操作就是把一个栈的元素全部倾倒到另一个栈内,但是会出现的问题是,如果有一个状态A和B的元素都相当多了,并且反复的进行merge操作,那么每一次merge都意味着大量的元素进出,肯定会超时的。因此,我们需要优化,优化方法是:再开一个栈com,merge的时候我们把A和B都清空,然后把这些元素放到com内即可。当进行pop操作时,如果当前栈是空的,那么就到com栈里面去找。这样的好处是,可以应付上面这个情况,如果反复merge,因为A和B都是空的,是不会进行操作的。另外要说明的一点是,显然对于每个元素它被移动到com里的次数是不会超过1次的,所以复杂度是O(n),再加上对优先队列的操作,总的复杂度是O(nlogn)。
参考博客:http://www.cnblogs.com/Sunshine-tcf/p/5753964.html。
代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <queue> 5 using namespace std; 6 7 struct node 8 { 9 int a,t; 10 bool operator < (const node &temp) const 11 { 12 return t < temp.t; 13 } 14 }; 15 16 int main() 17 { 18 int n,kase = 1; 19 while(scanf("%d",&n)==1 && n) 20 { 21 printf("Case #%d: ",kase++); 22 priority_queue<node> Q1,Q2,com; 23 for(int i=1;i<=n;i++) 24 { 25 char s1[10],s2[5],s3[5]; 26 int temp; 27 scanf("%s",s1); 28 if(strcmp(s1,"push")==0) 29 { 30 scanf("%s%d",s2,&temp); 31 if(s2[0]=='A') 32 { 33 Q1.push((node){temp,i}); 34 } 35 else 36 { 37 Q2.push((node){temp,i}); 38 } 39 } 40 else if(strcmp(s1,"pop")==0) 41 { 42 scanf("%s",s2); 43 if(s2[0]=='A') 44 { 45 if(!Q1.empty()) 46 { 47 node a = Q1.top();Q1.pop(); 48 printf("%d ",a.a); 49 } 50 else 51 { 52 node a = com.top();com.pop(); 53 printf("%d ",a.a); 54 } 55 } 56 else 57 { 58 if(!Q2.empty()) 59 { 60 node a = Q2.top();Q2.pop(); 61 printf("%d ",a.a); 62 } 63 else 64 { 65 node a = com.top();com.pop(); 66 printf("%d ",a.a); 67 } 68 } 69 } 70 else 71 { 72 scanf("%s%s",s2,s3); 73 while(!Q1.empty()) 74 { 75 node a = Q1.top();Q1.pop(); 76 com.push(a); 77 } 78 while(!Q2.empty()) 79 { 80 node a = Q2.top();Q2.pop(); 81 com.push(a); 82 } 83 } 84 } 85 } 86 return 0; 87 }