洛谷【P3952】NOIP2017提高组Day1T2时间复杂度

我对模拟的理解:http://www.cnblogs.com/AKMer/p/9064018.html

题目传送门:https://www.luogu.org/problemnew/show/P3952

作为一个在现场没有切出这题后来才(A)掉的弱鸡,我深感惭愧。

主要是因为在(Day1T1)上浪费了太多时间,导致根本没有时间写这道模拟题————出考场后我是这样想的,我还以为要是有时间我就可以(440)了————所以(Day1T2)我爆零了。

什么?你说这种水题我怎么还爆零?前(30)分不是送给我的吗?

说起我爆零的原因都有些感到颜面扫地……作为八中的学生我居然没分清楚大小写。一看题目,瞬间被(ERR)吸引住了眼球,然后把(Yes)当作了(YES),把(No)当作了(NO)……

但是今天我也花了1个多小时,在有数据的情况下才A掉,说明我的思维还是窄了点,想的不够全面。(440)不存在的,当初就算没看错大小写也就只有(370)……

我们只需要用栈维护循环语句开头与结尾的匹配,并且维护“每个循环内的最高时间复杂度”就可以了。假设在最外面再套一个不存在的循环,那么该循环内的最高时间复杂度就是题目要求的答案。

要注意一个循环内如果有多个互不干扰的循环,要用所有互不干扰的循环的复杂度取max更新当前循环的复杂度

时间复杂度:(O(n));

空间复杂度:(O(n));

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int inf=2e9;//把变量n当作inf

int n,T;
bool bo[30];//用来判断变量重名
char tim[20];

struct stence {
    int Max;//在此层循环内的时间复杂度最多是n^Max
    char opt[10],var[10],x[10],y[10];
}sta[200],s[200];//我用栈模拟,所有语句提前全部读完,不然我用solve会GG

int trans(char *a) {//将字符串转成数字
    if(a[1]=='n')return inf;
    int num=0,len=strlen(a+1);
    for(int i=1;i<=len;i++)
		num=num*10+a[i]-'0';
    return num;
}

bool solve() {
    int top=0,Maxtim=0;
    for(int i=1;i<=n;i++) {
		if(s[i].opt[1]=='F') {
			if(bo[s[i].var[1]-'a'])return 0;
			bo[s[i].var[1]-'a']=1;
			sta[++top]=s[i];
		}
		else {
            if(!top)return 0;
            int a=trans(sta[top].x),b=trans(sta[top].y);
            bo[sta[top].var[1]-'a']=0;
            if(a>b)sta[top].Max=0;//不会进入当前循环
            if(a!=inf&&b==inf)sta[top-1].Max=max(sta[top-1].Max,sta[top].Max+1);
            else if(a<=b)sta[top-1].Max=max(sta[top-1].Max,sta[top].Max);//一定要记得写成a<=b而不是a<b,相等也是会进入循环的
            if(top==1)Maxtim=max(Maxtim,sta[0].Max);
            top--;
        }
    }
    if(top)return 0;
    if(Maxtim==0&&tim[3]=='1')puts("Yes");
    else {
        int num=0,len=strlen(tim+1);
        for(int i=5;i<len;i++)
            num=num*10+tim[i]-'0';
        if(num==Maxtim)puts("Yes");
        else puts("No");
    }//判断正确与否
    return 1;
}

int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%s",&n,tim+1);
        memset(bo,0,sizeof(bo));//clear
        sta[0].Max=0;//sta[0]是假设的不存在的最外层的循环,根据定义,sta[0].Max就是答案
        for(int i=1;i<=n;i++) {
            scanf("%s",s[i].opt+1);
            if(s[i].opt[1]=='F')
				scanf("%s%s%s",s[i].var+1,s[i].x+1,s[i].y+1);
        }
        if(!solve())puts("ERR");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AKMer/p/9073149.html