【luogu P3952 时间复杂度】 题解
对于2017 D1 T2 这道题
实实在在是个码力题,非常考验耐心。
其实大体的思路并不是非常难想出来,但是要注意的小细节比较多。
题目链接:https://www.luogu.org/problemnew/show/P3952
思路
对于每一个程序,先读入L和O(),并将其中的时间复杂度抠出来。
其次整行读入字符串,即所给定的程序。
判断第一个字符是F or E
F i x y 需要把x y拿出来,把i压进栈
E 退栈 压进i后为了方便退栈及退栈时判断,用一个flag标记
每做完一个程序,与前面抠出来的时间复杂度对比判断yesnoerr即可。
注意
1.我的readx和ready函数比较暴力,直接截取常数和n可能存在的位置并保存。所以在考虑情况时,常数与n的位置不能搞错,也不能少考虑。
2.在每搞完一个程序时,要把初始值和标记都初始化一遍。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <stack> 6 using namespace std; 7 int L,t,anso,codeo;//anso=0 O(1) anso=x O(n^x) 输入给的时间复杂度 codeo 自己算的时间复杂度 if anso==codeo yes else no if codeo==-1 err 8 string code[105];//按行输入所给代码(F,E) 9 string ans;//读入给定的复杂度 O() 10 int readx(string x) 11 { 12 int num; 13 if(x[4] >= '0' && x[4] <= '9') num = x[4]-'0'; 14 if(x[5] >= '0' && x[5] <= '9') num = (x[4]-'0')*10+x[5]-'0'; 15 if(x[4] == 'n') num = 1000000; 16 return num; 17 } //抠出给定的复杂度 x 18 int ready(string x) 19 { 20 int num; 21 if(x[6] >= '0' && x[6] <= '9' && x[7] <= '0' || x[7] >= '9') num = x[6]-'0'; 22 if(x[7] >= '0' && x[7] <= '9' && x[8] <= '0' || x[8] >= '9') num = x[7]-'0'; 23 if(x[6] >= '0' && x[6] <= '9' && x[7] >= '0' && x[7] <= '9') num = (x[6]-'0')*10+x[7]-'0'; 24 if(x[7] >= '0' && x[7] <= '9' && x[8] >= '0' && x[8] <= '9') num = (x[7]-'0')*10+x[8]-'0'; 25 if(x[6] == 'n') num = 1000000; 26 if(x[7] == 'n') num = 1000000; 27 return num; 28 }//抠出给定的复杂度 y 29 int check1() 30 { 31 int res; 32 if(ans[2] == '1') res = 0; 33 if(ans[2] == 'n') 34 { 35 if(ans[4]<='9' && ans[4]>='0') 36 res = ans[4]-'0'; 37 if(ans[5]<='9' && ans[5]>='0') 38 res = (ans[4]-'0')*10 + ans[5]-'0'; 39 }//记录输入给的复杂度 40 return res; 41 } 42 int check2() 43 { 44 stack<int> s; 45 int flag=-1;//标记 46 bool fe[26]={0};//上面都是便于栈操作,fe来记录变量名 47 int res=0,now=0;//now来记录当前循环中的时间复杂度,res是整个程序的时间复杂度 48 bool cflag[26]={0};//记录变量是否重复 0 则没用过 1 用过 changeflag 49 int xnum,ynum; 50 51 for(int i=1;i<=L;i++) 52 { 53 54 if(code[i][0]=='F') 55 { 56 int k=code[i][2]-'a'; 57 if(cflag[k]) return -1; 58 s.push(k); 59 cflag[k] = 1; 60 61 xnum=readx(code[i]); ynum=ready(code[i]); 62 if(ynum-xnum>1000) 63 { 64 if(flag==-1) 65 { 66 now++; 67 res=max(res,now); 68 fe[k]=1; 69 } 70 } 71 if(xnum>ynum) 72 { 73 if(flag==-1) flag=k; 74 } 75 } 76 77 if(code[i][0]=='E') 78 { 79 if(s.empty()) return -1; 80 int k=s.top(); 81 s.pop();cflag[k]=false; 82 if(flag==k) flag=-1; 83 if(fe[k]) 84 { 85 fe[k]=false; 86 now--; 87 } 88 } 89 } 90 if(s.size()) return -1; 91 return res; 92 } 93 int main() 94 { 95 scanf("%d",&t); 96 while(t--) 97 { 98 99 scanf("%d ",&L);getline(cin,ans); 100 anso=check1(); 101 102 for(int i=1;i<=L;i++)getline(cin,code[i]); 103 codeo=check2(); 104 105 if(codeo==-1) cout<<"ERR"<<endl; 106 else 107 { 108 if(anso!=codeo) cout<<"No"<<endl; 109 if(anso==codeo) cout<<"Yes"<<endl; 110 } 111 } 112 return 0; 113 }
隐约雷鸣,阴霾天空,但盼风雨来,能留你在此。
隐约雷鸣,阴霾天空,即使天无雨,我亦留此地。