把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

NOIp2017D1T2 时间复杂度【模拟】

说一说

题目分析请从目录空降...

没想到模拟题还会卡这么久...菜得真实...

这是一个励志的故事:从0pts>9pts>18pts>27pts>36tps>54pts>72pts>84pts>100pts

(还不是面向数据编程,虽然这个分数的变化看来很像...)

题目分析

题目传送门

非常明显的模拟题。

FE的匹配关系可以想到像括号匹配那样用栈来做。(其实之前没有想到用栈的,是想用一个tot变量来判断能不能匹配,但是后面发现要找层次关系,要找E对应的F是什么)

我的做法是在线的,给出的程序只扫了一遍(当然还是存下来以便后续读取),主要思路就是:

用栈来维护,遇到一个F就压进去,tot++,标记变量已经被使用,顺便判断变量重名;遇到一个E就弹栈,弹出来的就是和自己配对的F,清除变量名的标记,计算自己这一层的复杂度:

常数->常数 —— 0

常数->n —— 1

n->n —— 0

n->常数 —— 0

并更新统计答案。再说一下重点,统计答案:(不知道有没有雷同的,感觉自己的思路很清奇,不一定说得清楚qwq)

之前想过用递归写,因为时间复杂度是同层取max,不同层累计(外层的答案相当于是内层的最大值+1/0(外层计算出来的自己这一层的复杂度))。

tot表示层级,比如:

 

 

 

每一层循环都用F开始那个tot标号,就可以表示层级关系。

定义数组ans[tot]表示tot这一层的答案,在这一层需要干的事情就是更新ans[tot]=max(ans[tot],ans[tot+1]+1/0

然后要将ans[tot+1]赋为0,是为了同一层并列的情况。和这一层并列的循环不能使用当前循环的循环体内嵌套的循环来更新它(这句话好像有点绕...)因为这里是碰到E了,马上就要tot,说明现在的tot+1是当前循环的内层循环,这个答案只能用来更新当前循环,而不能更新和当前循环并列的循环,而且进行到这一步说明内层循环已经没了,所以可以直接清成0

注意有个特殊情况,就是外层循环根本就进不去,也就是x>y,这个时候这一层的答案是0,这里可以把n看成INF

最后计算出来的时间复杂度是ans[1],把它和小明的答案进行比较就可以了。要注意小明的答案是用字符串读入的,而且有可能是个多位数,要转化成数字再和ans[1]比较。

遍历结束之后再看一下栈里面还有没有东西(或tot>=0),如果有,就ERR

判断ERR之后不要马上break,因为是多组数据而且是在线的,要把这组数据输入完,不然会影响后面数据的读入。

主要思路比较简单,但是细节有很多要处理,要小心。

复制代码
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<cstring>
  5 #include<queue>
  6 #include<map>
  7 #include<iostream>
  8 #include<stack>
  9 using namespace std;
 10 #define ll long long
 11 #define INF 0x3f3f3f3f
 12 int rd()
 13 {
 14     int f=1,s=0;char c=getchar();
 15     while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
 16     while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+(c^48);c=getchar();}
 17     return f*s;
 18 }
 19 char /*cd[105][20],输入太怀疑人生了*/opt[10];//不要在意这个名字(其实是因为懒得改了 
 20 bool vis[30];
 21 int ans[105]; 
 22 stack<int>s;
 23 struct node{
 24     string st,bl;
 25     int ss,tt;
 26 }cd[105];
 27 string t;
 28 int main() 
 29 {
 30     int T=rd();
 31     while(T--)
 32     {
 33         memset(ans,0,sizeof(ans));
 34         memset(vis,0,sizeof(vis));
 35         int L=rd();
 36         scanf("%s",opt+1);
 37         scanf("\n");
 38         bool flag=0;
 39         int tot=0;
 40         for(int i=1;i<=101;i++)
 41             cd[i].st="",cd[i].bl="",cd[i].ss=0,cd[i].tt=0;
 42         for(int i=1;i<=L;i++)
 43         {
 44             cin>>cd[i].st;
 45             if(cd[i].st[0]=='F')
 46             {
 47                 cin>>cd[i].bl;
 48                 string t;cin>>t;
 49                 if(t=="n") cd[i].ss=INF;
 50                 else 
 51                 {
 52                     for(int k=0;k<t.size();k++)
 53                         cd[i].ss=cd[i].ss*10+(t[k]-'0');
 54                 }
 55                 cin>>t;
 56                 if(t=="n") cd[i].tt=INF;
 57                 else 
 58                 {
 59                     for(int k=0;k<t.size();k++)
 60                         cd[i].tt=cd[i].tt*10+(t[k]-'0');
 61                 }
 62                 tot++;
 63                 s.push(i);
 64                 if(vis[cd[i].bl[0]-'a'])
 65                     flag=1;
 66                 vis[cd[i].bl[0]-'a']=1;
 67             }
 68             if(cd[i].st[0]=='E')
 69             {
 70                 if(s.empty())
 71                 {//这里要用栈 实际上后面的tot<0就是在判这个东西 但是这里已经调用了栈 所以没用 会RE 
 72                     flag=1;
 73                     continue;//break;不能break啊 多组数据要影响输入 
 74                 }
 75                 int k=s.top(),tmp=0;s.pop();
 76                 vis[cd[k].bl[0]-'a']=0;
 77                 if(cd[k].ss!=INF&&cd[k].tt==INF) tmp=1;
 78                 ans[tot]=max(ans[tot+1]+tmp,ans[tot]);
 79                 ans[tot+1]=0;
 80                 //注意这里清空 后面tot会-- 这一层已经搞完了 
 81                 //后面和这一层并列的东西不能从它的儿子部分得到 
 82                 if(cd[k].ss>cd[k].tt) ans[tot]=0;
 83                 tot--;
 84                 if(tot<0)
 85                 {
 86                     flag=1;
 87                     continue;//break;不能break啊 多组数据要影响输入 
 88                 }
 89             }
 90         }
 91         if(tot) flag=1;
 92         if(flag)
 93         {
 94             puts("ERR");
 95             continue;
 96         }
 97         //printf("%d\n",ans[1]);
 98         int res=0;
 99         int m=5;
100         while(opt[m]>='0'&&opt[m]<='9'){res=res*10+(opt[m]-'0');m++;}
101         if(ans[1]==0&&opt[3]=='1') puts("Yes");
102         else if(ans[1]==res) puts("Yes");
103         else puts("No");
104     }
105     return 0;
106 }
Code
复制代码

 

posted @   Starlight_Glimmer  阅读(167)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示