[NOIp2017] luogu P3952 时间复杂度

跪着看评测很优秀。

题目描述

给你若干个程序,这些程序只有 For 循环,求这些程序的时间复杂度。

Solution

大模拟。讲下细节。

f l a g [ i ] flag[i] flag[i] 表示第 i i i 位有没有对复杂度产生贡献,而且只有 F 开头的语句才会计算。
e d [ i ] ed[i] ed[i] 表示第 i i i 位配套的 E 的位置(第 i i i 位必须是 F)。
注意判 CE 的时候,

F x 2 1
	F x 1 2
	E
E

这个程序也要判 CE。


最后贴上代码

#include<cstdio>
#include<cstdlib>
#include<cstring>

#define max(x,y) ((x)>(y)?(x):(y))
#define ERR() {puts("ERR");return;}

int T;
int L,c;
char R[20];
int ans=0,now,h,cnt,cur;
char str[110][20];
int flag[110];
int x,y;
int st[110],ed[110];
bool bk[130];

int get(char*s,int t){
	int l=strlen(s);
	for(int i=0;i<l;++i){
		if(s[i]==' ') --t;
		if(!t){
			if(s[i+1]=='n') return 101;
			now=i;cnt=0;
			do{
				++now;
				cnt=cnt*10+s[now]-'0';
			}while(s[now+1]>='0'&&s[now+1]<='9');
			return cnt;
		}
	}
}
int count(int l,int r){
	if(ed[l]==r){
		if(flag[l]==1) return count(l+1,r-1)+1;
		else if(!flag[l]) return count(l+1,r-1);
		return 0;
	}
	int sum=0;
	for(int i=l;i<=r;i=ed[i]+1)
		sum=max(sum,count(i,ed[i]));
	return sum;
}
void work(){
	ans=0;
	if(R[3]=='1') ans=0;
	else{
		now=4;
		do{
			++now;
			ans=ans*10+R[now]-'0';
		}while(R[now+1]>='0'&&R[now+1]<='9');
	}
	for(int i=1;i<=L;++i){
		x=get(str[i],2);y=get(str[i],3);
		if(y==101&&x!=101&&str[i][0]=='F') flag[i]=1;
		else if(x>y) flag[i]=-1;
		else flag[i]=0;
	}
	memset(bk,0,sizeof(bk));
	memset(st,0,sizeof(st));h=0;
	memset(ed,0,sizeof(ed));
	for(int i=1;i<=L;++i){
		if(str[i][0]=='F'){
			++h;
			if(bk[str[i][2]]) {ERR();}
			else bk[str[i][2]]=1;
			st[h]=i;
		}
		else{
			ed[st[h]]=i;
			bk[str[st[h]][2]]=0;
			--h;
		}
		if(h<0) ERR() ;
	}
	if(h) ERR();
	puts((count(1,L)==ans)?"Yes":"No");
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%s",&L,R+1);
		getchar();
		for(int i=1;i<=L;++i)
			gets(str[i]);
		work();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值