hud 5929.Basic Data Structure

http://acm.hdu.edu.cn/showproblem.php?pid=5929

题意:一个只有0和1的双端队列,可以入栈,出栈,反转,求值(从现在的栈顶一直与非到栈底)

可能有20w次的操作,emmm菜逼挠了挠头感觉肯定有什么规律。奈何太菜没有发现,硬算一波果然超时.....只能去网上找大佬的代码看...

只需要记录两端最靠边的0的位置就好了,也就是两端连续的1的个数,因为从栈顶到最接近栈底的0之间的不管是什么,只要有东西(0不在栈顶),和那个0与非最后与非那个0得到的都是1,再根据这个0后面有几个连续的1就可以知道最后结果了

但是会有几种情况:

  • 没有0(都是1或者空的)(入栈的时候如果入1)
  • 只有一个0(两端最靠边的0是同一个)
  • 两个0(各是各的)
  • 只有一个0而且在某端点

每种情况入栈的时候会不同,具体看注释吧。出栈的时候维护好记录0位置(连续1的个数)的标志就好了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int T,I=1;
 6     scanf("%d",&T);
 7     while(T--)
 8     {
 9         printf("Case #%d:\n",I++);
10         int Y;
11         bool fa = 1,ze = 0;//fa是栈是否反转的标志,ze是栈中是否有0的标志
12         int t=0,w=0;//w表示栈为正(fa==1)的时候的栈底有几个连续的1,t表示栈为反(fa==0)时栈底有几个连续的1
13         deque<bool> de;//双端队列,啊真好用2333
14         scanf("%d",&Y);
15         char str[20];//存指令
16         while(Y--)
17         {
18             getchar();
19             scanf("%[^\n]",str);//读一整行到str中
20             switch(str[2])//通过指令的第三个字符判断
21             {
22             case 'S'://入栈
23                 if(fa)//没反转
24                 {
25                     de.push_front(str[5]=='1');//将数字入栈
26                     if(str[5]=='1')//如果入的是1的话t++
27                         t++;
28                     else
29                         t=0,ze=1;//如果入的是0,把t置零,ze置1
30                     if(!ze)w++;//如果入这个数字的时候栈里没有0(入的这个肯定是1),w也要++,因为如果栈里没有0那w和t就是长度
31                 }
32                 else//反转
33                 {
34                     de.push_back(str[5]=='1');
35                     if(str[5]=='1')
36                         w++;
37                     else
38                         w=0,ze=1;
39                     if(!ze)t++;
40                 }
41                 break;
42             case 'E'://求值
43                 if(!de.size())//栈空的话
44                     printf("Invalid.\n");
45                 else//非空的话
46                 {
47                     //偶数为0,奇数为1,0的时候也为1,w=0;w=size();w在中间
48                     int tem = fa==1?w:t;
49                     if(tem==0)//如果栈底没有连续1
50                         if(de.size()!=1)printf("1\n");//如果不是只有一个0的话结果肯定是1
51                         else
52                             printf("0\n");//如果栈里只有一个0的话结果就是0
53                     else if(tem==de.size()||tem==de.size()-1)//如果栈里没有0或者0在栈顶的话
54                         printf("%d\n",tem%2);
55                     else//如果0在中间(上面说的第三种情况)可以吧0看做1
56                         printf("%d\n",(tem+1)%2);
57                 }
58                 break;
59             case 'V'://反转
60                 fa=!fa;
61                 break;
62             case 'P'://出栈
63                 if(fa)
64                 {
65                     de.pop_front();
66                     t--;
67                     if(t<0)//没有刚刚出掉了个0要重新找离栈底最近的0(相当于求连续1的个数)
68                         for(t=0; t<de.size()&&de[t]!=false; t++);
69                     if(t==de.size())//没找到,说明栈里没有0
70                         ze=0;
71                 }
72                 else
73                 {
74                     de.pop_back();
75                     w--;
76                     int i=0;
77                     if(w<0)//没有刚刚出掉了个0要重新找离栈底最近的0(相当于求连续1的个数)
78                         for(w=de.size(); w>0&&de[w-1]!=false; w--,i++);
79                     if(w==0)//没找到,说明栈里没有0
80                         ze=0,w=i;
81                 }
82                 break;
83             }
84         }
85     }
86     return 0;
87 }

 

转载于:https://www.cnblogs.com/icfir/p/9022563.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值