【NOIP2017】【模拟】时间复杂度

【题目描述】
在这里插入图片描述
【输入格式】
在这里插入图片描述
【输出格式】
在这里插入图片描述

【样例输入】
8
2 O(1)
F i 1 1
E
2 O(n^1)
F x 1 n
E
1 O(1)
F x 1 n
4 O(n^2)
F x 5 n
F y 10 n
E
E
4 O(n^2)
F x 9 n
E
F y 2 n
E
4 O(n^1)
F x 9 n
F y n 4
E
E
4 O(1)
F y n 4
F x 9 n
E
E
4 O(n^2)
F x 1 n
F x 1 10
E
E
【样例输出】
Yes
Yes
ERR
Yes
No
Yes
Yes
ERR

【思路】

很清新的题目描述,也没什么思维难度。
遇到诸如此类的模拟,我们只需要冷静下来,一步一步实现就行了。对于题目中的各个操作的具体实现如下:

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");
	}
}

是不是很简单呀!

猜你喜欢

转载自blog.csdn.net/weixin_44111457/article/details/85944354