【NOIP2017】【模拟】时间复杂度
【题目描述】
【输入格式】
【输出格式】
【思路】
很清新的题目描述,也没什么思维难度。
遇到诸如此类的模拟,我们只需要冷静下来,一步一步实现就行了。对于题目中的各个操作的具体实现如下:
1.读入时间复杂度
其实也不复杂,主要是由于n的存在,因此我们必须以字符串的形式读入,特判一下是否为O(1)就ok了。唯一需要注意的就只有字符串转换数字了。
inline void get_time()
{
if(s[3]=='1')
time=0;
else
{
int lo=5;
while(s[lo]>='0'&&s[lo]<='9')time=time*10+s[lo]-'0',lo++;
}
}
2.创建新循环
由于无法进入的循环会导致它内部嵌套的所有循环都无法运行,因此我们需要一个栈来存储循环是否进入,同时方便退出循环。同时我们用map来实现变量判断是否使用过,用flag标记ERR的情况,用law表示当前循环能否执行,law=0则能执行,此时如果当前复杂度对总复杂度有贡献的话,则累加到now里面,并尝试用mx和now取max来记录当前最大时间复杂度。遇到无法执行的循环,则law++(注意这里不能仅仅让law=1,如果有多个不能执行的循环嵌套就会有问题,不能够判断无法执行的循环是否全部退栈),并直接让当前该循环时间复杂度=0就ok了。
inline void build(char nw,int a,int b)
{
flag=flag||f[nw];
f[nw]=1;//nw为新建变量
t[++top].bl=nw;
t[top].law=0;
t[top].time=0;
if(b<a)t[top].time=0,t[top].law=1,law++;//判断循环能否执行
if(b-a>1000)t[top].time=1;//当前循环对总复杂度有贡献
if(law)t[top].time=0;//无法执行的循环
now+=t[top].time;
mx=max(mx,now);
}
inline void add()
{
int a=0,b=0;
int lo=5;
while(s[lo]>='0'&&s[lo]<='9')a=a*10+s[lo]-'0',lo++;
if(!a)lo+=2,a=1e4;//此时没有读入任何数字,代表a=n。
else lo++;
while(s[lo]>='0'&&s[lo]<='9')b=b*10+s[lo]-'0',lo++;
if(!b)b=1e4;//此时没有读入任何数字,代表b=n。
build(s[3],a,b);
}
3.结束一层循环
首先,我们需要取消对变量的标记,然后更新当前时间复杂度。如果当前循环是不能执行的循环,则law–,方便判断接下来的循环能否执行。同时这里我们需要考虑一种ERR的情况,就是top<0,意味着当前E和F不匹配,那么就让flag=1。
inline void pop()
{
f[t[top].bl]=0;
now-=t[top].time;
if(t[top].law)law--;
top--;
if(top<0)flag=1;
}
至此,这道题就大功告成啦,细节问题详见代码。
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<tr1/unordered_map>
#include<bits/stdc++.h>
#define re register
using namespace std;
int t;
tr1::unordered_map<char,bool>f;
char s[10001];
struct node{
char bl;
int time;
bool law;
};
struct stck{
int top,time;
bool flag;
int now;
int law;
int mx;
node t[10001];
inline void clear()
{
memset(t,0,sizeof(t));
top=0;
flag=0;
time=0;
now=0;
mx=0;
law=0;
}
inline void get_time()
{
if(s[3]=='1')
time=0;
else
{
int lo=5;
while(s[lo]>='0'&&s[lo]<='9')time=time*10+s[lo]-'0',lo++;
}
}
inline void build(char nw,int a,int b)
{
flag=flag||f[nw];
f[nw]=1;
t[++top].bl=nw;
t[top].law=0;
t[top].time=0;
if(b<a)t[top].time=0,t[top].law=1,law++;
if(b-a>1000)t[top].time=1;
if(law)t[top].time=0;
now+=t[top].time;
mx=max(mx,now);
}
inline void add()
{
int a=0,b=0;
int lo=5;
while(s[lo]>='0'&&s[lo]<='9')a=a*10+s[lo]-'0',lo++;
if(!a)lo+=2,a=1e4;
else lo++;
while(s[lo]>='0'&&s[lo]<='9')b=b*10+s[lo]-'0',lo++;
if(!b)b=1e4;
build(s[3],a,b);
}
inline void pop()
{
f[t[top].bl]=0;
now-=t[top].time;
if(t[top].law)law--;
top--;
if(top<0)flag=1;
}
}q;
inline void work()
{
if(s[1]=='F')
q.add();
else q.pop();
}
int main()
{
scanf("%d",&t);
while(t--)
{
int hs;
q.clear();
scanf("%d ",&hs);
gets(s+1);
q.get_time();
for(int re i=1;i<=hs;i++)
{
gets(s+1);
work();
}
while(q.top>0)q.pop(),q.flag=1;
if(q.top<0)q.flag=1;
if(q.flag)puts("ERR");
else if(q.mx==q.time)puts("Yes");
else puts("No");
}
}
是不是很简单呀!