NOIP 2017 时间复杂度
模拟+字符串
作为一个代码能力极其一般的蒟蒻,这道题算是整个代码能力训练中比较好写的一道了。注意读入部分要预处理很多细节,正如先辈们说的,写一点调一点就能极大程度减少后期调代码的难度。
开始说细节:
-
读入一定要离线后再进行预处理,如果在线会导致整个细节非常复杂,用字符串保存每一行输入的代码,有一个极早时期就学过的语法用来读入一整行的字符 getline(cin,s)
-
对于每一个'F',在一个stack中维护具体的该层循环复杂度,对于每一个’E‘,在stack中去除一层,完美符合了真实情况下for循环的复杂度计算方式。
-
复杂度计算上,对于一层复杂度为0的循环其内其余循环均无法产生贡献,开一个标记保存。
-
出现“ERR”即’F‘与’E‘个数不一样多,stack维护自身大小,出错直接return
#include<bits/stdc++.h>
using namespace std;
const int N=105;
int t,n,com,vis[30],gx[30];
string s,cd[N];
inline int confirm()
{
int res=0,now=0,tmp=-1;
stack<int> st;
for(int i=1;i<=n;i++)
{
if(cd[i][0]=='F')
{
int cur=cd[i][2]-'a'+1,a=0,b=0;
if(vis[cur])return -1;
st.push(cur);vis[cur]=true;
bool flag=false;
for(int j=4;j<cd[i].size();j++)
{
if(!flag)
{
if(cd[i][j]=='n')
{a=1000000;flag=true;continue;}
else
{
while(isdigit(cd[i][j]))
a=a*10+cd[i][j++]-'0';
flag=true;continue;
}
}
else
{
if(cd[i][j]=='n')
{b=1000000;break;}
else if(isdigit(cd[i][j]))
{
while(isdigit(cd[i][j]))
b=b*10+cd[i][j++]-'0';
break;
}
}
}
if(tmp==-1)
{
if(b-a>1000)
res=max(res,++now),gx[cur]=true;
if(a>b)tmp=cur;
}
}
if(cd[i][0]=='E')
{
if(st.empty())return -1;
int tp=st.top();st.pop();
vis[tp]=false;
if(tmp==tp)tmp=-1;
if(gx[tp])gx[tp]=false,now--;
}
}
if(!st.empty())return -1;
else return res;
}
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
memset(gx,0,sizeof(gx));
memset(vis,0,sizeof(vis));
bool flag=false;
cin>>n;com=0;
getline(cin,s);
for(int i=0;i<s.size();i++)if(s[i]=='O')
{
flag=true;
if(s[i+2]==1)com=0;
else
{
i+=4;
while(isdigit(s[i]))com=com*10+s[i++]-'0';
}
break;
}
for(int i=1;i<=n;i++)getline(cin,cd[i]);
int ans=confirm();
if(ans==-1)cout<<"ERR"<<endl;
else
{
if(ans==com)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
}