P3952 时间复杂度(模拟)

题目链接

题解:
好恶心的模拟题…调了一晚上…

题意让我们模拟循环,同时判断语法是否有误,并计算时间复杂度是否一致

首先考虑有没有语法错误:
我们先将’n’置于一个比较大的数字,flag=-1;
利用一个栈S,遍历一遍代码,如果是F,则记录变量名,将k进栈。
1.如果b>a,那么没有进入循环,用一个flag保存最早的没有进入的下标k,mark标记
2.如果a≤b,代表进入循环,那么判断循环上下限是否>200并且flag是否为-1,若都满足,说明本层循环是有贡献的,那么让当前的循环层+1,
如果返回时遇到了最初没有进入循环的k,我们将它的mark消除即可

如果是E,那么同样要记录变量名,将变量名k弹出,同时判断flag是否等于当前k,如果是,则表示已经出了没有贡献的循环,再判断当前k是否对复杂度有贡献即可

最后判断栈S是否为空(类似于括号匹配),不为空,同样返回“ERR”

最后返回语法正确的时间复杂度,判断即可


AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 105;
string op[MAXN],ss;
bool vis[30],mark[30]; int n;
inline int Int(int &x,string s){
    int res=0,len=s.size();
    while(s[x]<'0' || s[x]>'9' && x<s.size()){
        if(s[x]=='n') { ++x;return 100000; }
        ++x;
    }
    while(s[x]>='0' && s[x]<='9') res=res*10+s[x]-'0',++x;
    return res;
}
inline int get(){
    int res=0,x=3,len=ss.size();
    if(ss[2]=='n') return Int(x,ss);
    else return 0;
}
inline int solve(){
    int res=0,now=0,a,b,x,flag=-1;
    stack<int> s;
    memset(vis,0,sizeof(vis)); memset(mark,0,sizeof(mark));
    for(int i=1;i<=n;i++){
        if(op[i][0]=='F'){
            int p=op[i][2]-'a';
            if(vis[p]) return -1;
            s.push(p); vis[p]=true; x=4;
            a=Int(x,op[i]); b=Int(x,op[i]);
            if(b-a>1000){
                if(flag==-1) { now++; res=max(res,now); mark[p]=true; }
            }
            if(a>b && flag==-1) flag=p;
        }else if(op[i][0]=='E'){
            if(s.empty()) return -1;
            int k=s.top(); s.pop();
            vis[k]=false;
            if(flag==k) flag=-1;
            if(mark[k]) { mark[k]=false; now--; }
        }
    }
    if(s.size()) return -1;
    return res;
}
int main(){
    //freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d ",&n); getline(cin,ss);
        int tag = get();
        for(int i=1;i<=n;i++) getline(cin,op[i]);
        int ans=solve();
        if(ans==-1) puts("ERR");
        else if(ans==tag) puts("Yes");
        else puts("No");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值