【Noip2017】D1T2时间复杂度(complexity)

今天,时隔多年我感觉今天状态非常的好,所以非常耐心的打出了这道题,然后AC了。

其实这道题也是一道Dark 模拟了。如果大家想要入门这道题的话,这里有一个非常好的题

题目传送门:P4711 「化学」相对分子质量

题解传送门:P4711 「化学」相对分子质量【题解】

下面我就来讲一讲AC这道题我们需要的一些基本工作。

1、首先我们发现这道题中我们要处理一些数字,所以就还是像上面一样我们需要写一个函数来帮助我们来提取字符串中的数字部分,所以原理还是和上面一样的。

2、本题还有一个不一样的地方,就是我们判断时间复杂度时,我们每一个循环中不仅仅会出现数字,还会出现字母。如果两个都是数字,那么他对时间复杂度是没有贡献的,但是一定要注意如果两个都是字母那么他也对时间复杂度没有任何贡献,只有一个数字一个字母才有贡献,那么这个时候我们如何对字母进行处理呢?其实我们只需要当我们读到字母转化成一个非常大的数字就可以了。这样我们只要判断两个数的差是否大于1000或更大就可以判断他对时间复杂度有没有贡献了。

3、其实本题最难的地方不在上面所说的两个点上,而是在如何计算该时间复杂度上,还有如何判断语法错误上。

下面我们就来对这个东西详细讲解一下:

我们为了要使我们能够确定F和E的对应关系,我们决定使用栈这种数据结构,我们把每一次定义的char类型存入栈中,这样我们可以实现一举两得的效果,我们不仅可以更好的把F和E进行匹配,也可以更方便的销毁已经结束循环的变量,我们在使用读取数字大小的函数对a,b进行读取,然后判断他们的大小,一定要注意,如果出现了a>b的情况,那么我们可以发现这个循环是进入不了的所以这个时候我们要进行特判,定义一个flag变量,如果该flag变量不是-1说明他下面的循环都进入不了,我们就不用增加深度(now)如果是-1就可以增加深度并且更改该点的影响值(ef)为真。这样在后面我们找到了与F配对的E时我们才可以把当前深度进行减少(now--)

相信大家认真阅读上面的这一段的话,还是可以懂我在说什么意思的。那么大家对照代码看应该会更加理解这个意思:

代码如下:

#include<bits/stdc++.h>
using namespace std;
string ch[104];
string o;
int n,len;
int number(int &x,string c)
{
	int ans=0;
	int len=c.size();
	while((c[x]<'0' || c[x]>'9')&&x<c.size()) {
        if(c[x]=='n'){
            ++x;
            return 1000000;
        }
        ++x;
    }
    while(c[x]>='0'&&c[x]<='9')
    {
    	ans=ans*10+c[x]-'0';
    	x++;
    }
    return ans;
}
int check()
{
	int ans=0;
	int now=0;
	stack<int> stk;
	bool ins[26];
	bool ef[26];
	int flag=-1;
	memset(ef,false,sizeof(ef));memset(ins,false,sizeof(ins));
	for(int i=1;i<=len;++i)
	{
		if(ch[i][0]=='F')
		{
			int k;
			k=ch[i][2]-'a';
			if(ins[k])return -1;
			ins[k]=true;
			stk.push(k);
			int x=4;
			int a=number(x,ch[i]),b=number(x,ch[i]);
			if(b-a>1000)
			{
				if(flag==-1)
				{
					now++;
					ans=max(now,ans);
					ef[k]=true;
				}
				
			}
			if(b-a<0)
			{
				if(flag==-1)flag=k;
			}
		}
		if(ch[i][0]=='E')
		{
			if(stk.empty()) return -1;
			int k=stk.top();stk.pop();
			ins[k]=false;
			if(flag==k) flag=-1;
			if(ef[k])
			{
				now--;
				ef[k]=false;
			}
		}
	}
	if(stk.size()) return -1;//一定要判断最后栈被清空没有,如果没有清空说明F还没有被完全匹配,所以有语法错误 
	return ans;
}
int O()
{
	if(o[3]=='1') return 0;
	else
	{
		int x=0,cnt=0;
		while(o[cnt]<'0'||o[cnt]>'9') cnt++;
		while(o[cnt]>='0'&&o[cnt]<='9')
		{
			x=x*10+o[cnt]-'0';
			cnt++;
		}
		return x;
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%d",&len);
		getline(cin,o);
		int judger=O();
		for(int j=1;j<=len;++j)
		{
			getline(cin,ch[j]);
		}
		int che=check();
		if(che==judger) {printf("Yes\n");}
		else if(che==-1) printf("ERR\n");
		else printf("No\n");
	}
}

谢谢采纳!

posted @ 2020-07-17 08:45  Mudrobot  阅读(170)  评论(0)    收藏  举报