【正经题解】时间复杂度
2024-02-22 11:47:57
发布于:浙江
21阅读
0回复
0点赞
首先开两个双端队列,一个存所有的循环变量,另一个存参加循环的循环变量。然后根据输入计算出是 的几次方的复杂度( ( ))为 的 次方,然后 输入可以输入带空格的字符串,然后对每行开头是 或 的情况分别讨论,用 变量分类输出即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#define maxn 100+1
using namespace std;
inline int qread()
{
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
int l,t,vis[maxn],in[maxn]; //l和t分别为题目中的l和t,vis数组表示这个循环变量是否在第一个双端队列中,in为第二个。
string s;
int main()
{
t=qread();
while(t--)
{
memset(vis,0,sizeof(vis)); //对于每组数据,vis和in都要清空。
memset(in,0,sizeof(in));
deque<int>q1,q2; //双端队列。
scanf("%d",&l);
getline(cin,s); //getline可以读入带空格的字符串。
int cf,sum=0,stop=0,f=0; //cf表示当前程序题目给出的时间复杂度,sum表示当前程序实际的时间复杂度,f用来分类输出。
if(s[3]=='1') cf=0; //O(1)即O(n的0次方)。。。为什么这里是s[3]?因为先输入的一个l,然后有个空格,这个空格是占数组位置的,数组位置从0开始。
else
{
int now=5;cf=0; //同理。
while(isdigit(s[now])) cf=cf*10+s[now++]-'0'; //跟快读原理一样。
}
while(l--) //对于每个循环的开头进行讨论。
{
getline(cin,s);
if(s[0]=='F')
{
int x=s[2]-'a'+1; //把循环变量转化为int类型。
q1.push_front(x); //加入第一个队列。
if(!vis[x]) //如果x未被标记。
{
vis[x]=1; //标记。
if(s[4]=='n')
{
if(isdigit(s[6]))
stop=1; //如果循环从n开始,并且循环右端点不是n,那么这个语句不参与循环。
}
else //循环不从n开始。
{
int now=4,t1=0,t2=0;
while(isdigit(s[now])) t1=t1*10+s[now++]-'0'; //调出起点。
if(s[now+1]=='n'&&stop==0) //如果循环右端点是n并且当前语句参与循环。
{
q2.push_front(x); //参与循环加入第二个队列中。
in[x]=1; //标记。
int m=q2.size(); //第二个队列中有几个循环变量并且循环右端点都是n,那么复杂度就是O(n的几次方)。
sum=max(m,sum); //更新实际复杂度。
}
if(s[now+1]!='n') //若循环右端点不为n,那么表明循环左右端点都是常数(左端点为n的已经判完了)。
{
now++;
while(isdigit(s[now])) t2=t2*10+s[now++]-'0'; //计算出循环右端点。
if(t2<t1) stop=1; //如果右端点小于左端点,不参与循环。
}
}
}
else f=1; //否则,就有语法错误。
}
if(s[0]=='E') //如果行的开头为E。
{
if(!q1.empty()) //当第一个队列不为空。
{
int p=q1.front();
q1.pop_front(); //弹出队首。
if(in[p]) //如果队首元素也在第二个队列里。
{
q2.pop_front(); //弹出来。
in[p]=0; //释放标记。
}
vis[p]=0; //释放标记。
}
else f=1; //不然,就存在语法错误。
if(q1.empty()) stop=0; //如果第一个队列中没有元素了,该循环体就执行完了。
}
if(s[0]!='F'&&s[0]!='E') f=1; //如果行首出现其他字母,则是语法错误。
}
if(!q1.empty()) f=1; //最后,如果第二个队列还有循环元素(E都没了还有元素),则有语法错误。
if(f==1)
{
cout<<"ERR"<<'\n'; //先把语法错误判掉,以免给出复杂度和实际复杂度不符时把f=1覆盖成2。
continue;
}
if(sum!=cf) f=2; //实际复杂度跟给出复杂度不统一。
if(f==0) cout<<"Yes"<<'\n';
if(f==2) cout<<"No"<<'\n'; //分类输出就好了。
}
return 0;
}
这里空空如也
有帮助,赞一个