[FROM WOJ]#2748 时间复杂度

以后直接放链接了,哈哈蛤……

#2748 时间复杂度

传送门

SOL
循环的结构很简单:

F i x y
循环体
E

但是作为一道模拟题这道题的细节很多……
输入
尽量不要一行直接一个字符串读完,例如“F i x y”类型的读入可以考虑先读入“F”,然后分别读入后面三个。
另外O(1)可以视作w=0。
中间信息的统计
用一个栈来统计中间出现过的循环。
读完题后可以发现每层循环的复杂度只有三种情况,三类情况可以分别用0、1、2存储:

0 不循环
1 常数
2 n

该操作的实现详见代码

判断ERR
显然可以直接用栈判断,然后一行是F语句时top++,E语句时top–,top–时判断一下是否合法即可,可以有一个bool变量来记录是否出现ERR,这样以后可以直接continue.
判断Yes/No
由于 L < = 100 L<=100 L<=100,显然可以考虑每次进入E语句时暴力枚举一下栈中所有元素的复杂度即可,注意当遇到未进入的循环(x>y)时直接break即可

代码:

#include<bits/stdc++.h>
#define re register
using namespace std;
const int n=100;
int T,L;
char O[10],op,i,x[5],y[5];
bool vis[26];
struct node{char var;int tim;}stk[101];
inline int get(char *s,int sum=0){
	int re len=strlen(s);
	for(int re tt=0;tt^len;++tt)sum=(sum<<1)+(sum<<3)+(s[tt]^48);
	return sum;
}
inline int calc(int m){
	int re ret=0;
	for(int re tt=1;tt<=m;++tt){
		ret+=(stk[tt].tim==2);
		if(!stk[tt].tim)break;
	}return ret;
}
signed main(){
	scanf("%d",&T);
	while(T--){
		memset(vis,false,sizeof(vis));
		int re w=0,ans=0,top=0;bool err=0;
		scanf("\n%d%s",&L,O);
		if(O[2]=='n')for(int re tt=4;isdigit(O[tt]);++tt)w=(w<<1)+(w<<3)+(O[tt]^48);
		else w=0;
		while(L--){
			scanf("\n%c",&op);
			if(op=='F'){
				scanf(" %c%s%s",&i,x,y);
				if(err)continue;
				int re xx=0,yy=0;
				if(x[0]=='n')xx=1;if(y[0]=='n')yy=1;
				if(vis[i-'a']){err=1;continue;}
				vis[i-'a']=1,stk[++top].var=i,stk[top].tim=yy-xx+1;
				if(xx||yy)continue;
				if(get(x)>get(y))stk[top].tim=0;
			}
			else{
				if(!top)err=1;
				if(err)continue;
				ans=max(ans,calc(top)),vis[stk[top--].var-'a']=0;
			}
		}
		if(top)err=1;
		if(err){puts("ERR");continue;}
		puts(ans==w?"Yes":"No");
	}exit(0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值