NOIP 2017 Day1 T2 时间复杂度

 

Luogu题面

大模拟...并不难(然而考场上写挂了

 

3 个读入函数,解决读入问题

双栈齐发,一个记录使用过的字母,另一个记录复杂度贡献情况

bre 表示当前跳出循环的层数

err 表示当前编译状态是否编译失败

sans 分别表示当前复杂度总复杂度

 

那么当读取到 'F时,我们就要做以下几点

  1. 读取循环中使用的字母,并判断其是否被使用过,并将其标记为已使用;
  2. 读取循环的起止值,判断其能否被进入,并且处理好跳出循环的层数;
  3. 判断该循环对复杂度的贡献情况,处理好 s 和 ans ;

当读取到 ‘E’ 时要做以下几点

  1. 弹出两栈栈顶元素,将弹出的变量销毁;
  2. 处理好编译错误的情况和循环的跳出层数;

 

代码短小精干(1kb),通俗易懂:

#include<bits/stdc++.h>
using
namespace std; bool use[256]; stack<char>q; // 记录循环变量
stack<int>p; // 记录循环对复杂度的贡献情况 inline int getnum(){ // 读取下一个数字 char ch=getchar(); int x=0; while((ch<'0'||ch>'9')&&ch!='n') ch=getchar(); // 除了'n',别的都无脑跳过 if(ch=='n') return 100; // 数字最大 99,设 n == 100 方便处理 while(ch>='0'&&ch<='9') x=x*10-48+ch,ch=getchar(); return x; } inline char get(){ // 读取下一个字符(非空格和回车) char ch=getchar(); while(ch==' '||ch=='\n') ch=getchar(); return ch; } inline int getn(){ // 判断能否读取到'n'(感觉好多余啊) if(getnum()==100) return 1; return 0; } int main(){ int t=getnum(); while(t--){ memset(use,0,sizeof(use)); // 初始化 int n=getnum(),f=getn(),err=0,s=0,bre=0,ans=0,ch; // 一堆变量 if(f) f=getnum(); // f 表示复杂度的指数(这两行的读入很精髓哦) while(n--) if(get()=='F'){ // 开始乱搞... q.push(ch=get()); if(use[ch]) err=1; use[ch]=1; // 以上三行处理变量 int l=getnum(),r=getnum(); if(l>r||bre) bre++; // 自行体会对于跳出层数的处理 if(l<r&&r==100&&!bre) s++,p.push(1),ans=max(s,ans); // 对复杂度产生 1 贡献 else p.push(0); // 没有贡献 } else{ if(!p.empty()) s-=p.top(),use[q.top()]=0,p.pop(),q.pop(); // 各种操作(压行大法好) else err=1; if(bre) bre--; } while(!q.empty()) err=1,q.pop(),p.pop(); // 将栈弹空(如果栈非空则编译错误) printf(err?"ERR\n":ans==f?"Yes\n":"No\n"); // 三目运算符简化代码(懒...) } return 0; // ...... }

 

By The_Seventh

2017-12-24  09:23:53

posted @ 2017-12-24 09:24  The_Seventh  阅读(278)  评论(1编辑  收藏  举报