NOIP2017 时间复杂度

传送门

这道题我去年做到爆炸,最后还是爆零了,现在我还是特别慢才写完……

唯一不同就是现在思路比较清晰,但是我的做法比较复杂,代码很长。

我们要处理以下事情:

1.读入程序行数,得到该程序时间复杂度。

这个很简单,我的方法是写一个函数判断一下,然后返回当前时间,如果是常数级就是0.

2.读入程序,判断是否合法。

这一步判断只需要判断变量是否重复即可,不合法直接退出。

3.判断能否进入这次循环。

因为scanf遇到空格会停下,所以我直接使用string来处理。我们要处理的其实就是一个数和n,我写了一个函数进行判断。

4.如果不能进入循环,进入查错状态。

如果不能循环,那么里面的代码没什么用,只能查错。这个还是很舒服的,因为里面就不用考虑能不能进入循环,只考虑是否合法即可。还是自写了一个函数进行判断,只判断变量名重复。之后如果当前栈顶比进来的时候还少,那就从查错状态中返回。

5.能进入循环,进行压栈,更新答案。

这个不用多说了,注意每次的时间也要压入栈中,否则因为我是在线处理的,循环结束的时候你不知道自己应不应该减时间。注意每次压栈都要更新一次当前的最大复杂度。

6.判断循环结束。

这个也很简单,每次把栈还原即可。

7.判断合法。

如果程序结束的时候栈中还有元素或栈中无元素还在往外弹,那就不合法。

注意因为我的方法是直接跳出,所以即使程序不合法也要全部读完。

8.输出结果。

其他注意事项是注意每次保险起见清空数组,之后要记录当前读到哪了,查错和普通状态下都要++。

感觉自己临近NOIP码力仍然很弱……时间不多了。

看一下代码。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('
')
#define pr pair<int,int>
#define mp make_pair
#define fi first
#define sc second
using namespace std;
typedef long long ll;
const int M = 100005;
const int N = 10000005;
 
int read()
{
   int ans = 0,op = 1;
   char ch = getchar();
   while(ch < '0' || ch > '9')
   {
      if(ch == '-') op = -1;
      ch = getchar();
   }
   while(ch >='0' && ch <= '9')
   {
      ans *= 10;
      ans += ch - '0';
      ch = getchar();
   }
   return ans * op;
}

int T,L,sta[1005],top,maxn,maxt,csta[1005],ctop,sen;
bool vis[105];
string s,vari,fir,la;

void clear()
{
   memset(sta,0,sizeof(sta)),top = 0;
   memset(csta,0,sizeof(csta)),ctop = 0;
   memset(vis,0,sizeof(vis)),maxn = sen = 0;
}

int caltime()
{
   if(s[2] == '1') return 0;
   int k = 4,cur = 0;
   while(s[k] >= '0' && s[k] <= '9') cur *= 10,cur += s[k] - '0',k++;
   return cur;
}

bool illegal()
{
   return vis[vari[0] - 'a' + 1];
}

bool in()
{
   if(fir[0] == 'n') return la[0] == 'n';
   int cur = 0,cur1 = 0;
   rep(i,0,fir.length()-1) cur *= 10,cur += fir[i] - '0';
   if(la[0] == 'n') return 1;
   rep(i,0,la.length()-1) cur1 *= 10,cur1 += la[i] - '0';
   return cur < cur1;
}

bool addtime()
{
   if(fir[0] == 'n') return 0;
   return la[0] == 'n';
}

bool check()
{
   int d = top;
   while(1)
   {
      sen++;
      cin >> s;
      if(s[0] == 'F')
      {
     cin >> vari >> fir >> la; 
     if(illegal()) return 0;
     else sta[++top] = vari[0] - 'a' + 1,vis[sta[top]] = 1;
      }
      else if(s[0] == 'E')
      {
     vis[sta[top]] = 0,sta[top--] = 0;
     if(top == d - 1) return 1;
      }
   }
}

bool solve(int L,int ctim)
{
   int maxt = maxn = 0;
   while(sen < L)
   {
      sen++,cin >> s;
      if(s[0] == 'F')
      {
     cin >> vari >> fir >> la;
     if(illegal()) return 0;
     if(!in())
     {
        sta[++top] = vari[0] - 'a' + 1,vis[sta[top]] = 1;
        if(!check()) return 0;
     }
     else
     {
        sta[++top] = vari[0] - 'a' + 1,vis[sta[top]] = 1;
        csta[++ctop] = maxt,maxt += addtime();
        maxn = max(maxn,maxt);
     }
      }
      else
      {
     if(!top) return 0;
     vis[sta[top]] = 0,sta[top--] = 0,maxt = csta[ctop--];
      }
   }
   if(top) return 0;
   return 1;
}

int main()
{
   T = read();
   while(T--)
   {
      clear();
      L = read(),cin >> s;
      int ctim = caltime();
      if(!solve(L,ctim)) printf("ERR
");
      else (maxn == ctim) ? printf("Yes
") : printf("No
");
      while(sen < L)
      {
     cin >> s;
     if(s[0] == 'F') cin >> vari >> fir >> la;
     sen++;
      }
   }
   return 0;
}
原文地址:https://www.cnblogs.com/captain1/p/9880418.html