当前位置: 首页 > news >正文

NOIp2017 D1T2

前情提要

夏令营教模拟,老师给了我们这个作业。我当时特喜欢刷水题。当时,我觉得这道题很水,轻松搞定,于是直奔满分而去。结果......也就调了亿会。

为了弥补这一个月之劳累,特写此题解。

铺垫

(注:这里我用字符串存储小明认为的复杂度。)

定义该循环“对复杂度有贡献”当且仅当循环下界与上界之差远大于 \(100\)。这种循环是我们要统计的。

定义“废循环”为不对复杂度的次数有贡献的循环。这种循环是需要避免计算入复杂度的。

处理语法错误的方法

一个程序语法错误当且仅当:(括号内为解决方案)

  • 变量重名;(用 \(arr\) 数组记录变量是否被使用)
  • FE 不对应。(用栈模拟循环)

正片

本题解着重讲解模拟思路,想倒不难。

处理复杂度步骤描述

首先:读入每行程序的第一个字符。

F:处理此循环的标记

  • 读入变量名、循环下界和上界。
  • 如果和 \(arr\) 数组之前记录的变量名重名:
    • 标记语法错误,重新读入,忽略该组程序。(避免重复输出)
    • 否则:
      • \(arr\) 数组中标记变量名,并将变量名压入循环栈中;(方便销毁变量名)
      • n 赋值为一个极大值;(方便计算复杂度)
      • 如果这个循环没有被标记为废循环,且循环对复杂度有贡献:
        • 将该循环标记为有贡献的;
        • 当前次数 \(w\to w+1\)
        • 更新最大次数 \(res\)
      • 否则:
        • 标记该变量名下的循环为废循环。
if(a == 'F'){cin >> b >> c >> d;if(arr[b - 'a'] && !ERR){cout << "ERR\n";ERR = 1; continue; //变量名重复} else {arr[b - 'a'] = 1;st.push(b); if(c == "n"){ c = "20000";}if(d == "n"){ d = "20000";}int C = stoi(c), D = stoi(d);if(D-C > 1000 && flag == -1){eff[b - 'a'] = 1; ++w;res = max(w, res);//判定复杂度} else if(C > D){flag = b; //废循环}}
}

E:撤销之前对与之对应的循环的标记

  • 如果这个栈是空的:
    • 标记语法错误,重新读入,忽略该组程序。
  • 否则:
    • 取出栈顶的变量名;
    • 从栈中弹出这个循环;
    • 撤销变量名重名标记;
    • 如果该变量名下的循环为废循环:
      • 撤销废循环标记。
    • 否则,如果该变量名下的循环对复杂度有贡献:
      • 撤销贡献标记,当前次数 \(w\to w-1\)
else {if(st.empty()){if(! ERR){cout << "ERR\n"; ERR = 1;} continue;} int cur = st.top();st.pop();arr[cur - 'a'] = 0;if(flag == cur) { flag = -1; }if(eff[cur - 'a']) {eff[cur - 'a'] = 0;w --;}
}

收尾,判定复杂度

  • 如果栈中还有元素:
    • 清空栈;
    • 如果没有输出过 ERR
      • 报告语法错误。
    • 读入下一组数据。
  • 特判 O(1),即 \(\Theta(n^0)\)
    • 如果语法正确且最终次数 \(res\)\(0\)
      • 输出 Yes
    • 否则:
      • 输出 No
  • 否则截取复杂度的次数部分。\(^{[1]}\)(将截取的字符串转换为 int 类型)
  • 如果次数部分等于 \(res\)
    • 输出 Yes
  • 否则:
    • 输出 No

\([1]\):这类格式以 O(n^45) 为例。前 \(4\) 个字符为固定的,不为数字;最后一个字符为 )。所以,截取数字要从第 \(5\) 个字符开始(即 s[4]4)到倒数第二个字符(s[s.size() - 1]5),即可截取到 45

if(st.size()){while(st.size()){st.pop();}if(!ERR) {cout << "ERR\n";}continue;
}
if(s == "O(1)" && !ERR){if(res == 0) {cout << "Yes\n";} else {cout << "No\n";}
} else if(!ERR) {string s1;for(int i=4; i<s.size()-1; ++i){s1 += s.substr(i, 1);}if(stoi(s1) == res) {cout << "Yes\n";} else {cout << "No\n";}
}

坑总结

  1. 多测必清空!
  2. 想好思路再写代码;
  3. 把语法错误的循环完全忽略。记录是否属于这类循环,并尽量在所有判断的条件加上 ! ERR
  4. 特判循环下界和上界都是 n 的情况;
  5. 小明判定的复杂度中,次数可能不止一位。

总代码

模拟题最重要的是细节和思维。想到了思路,你完全可以敲出正解代码。此处建议自行编写。

#include <bits/stdc++.h>
using namespace std;
int _;
bool arr[30], eff[30];int main(){ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);stack<int> st;cin >> _;while(_ --){int n, w=0, res=0, flag = -1, ERR = 0;string s, c, d;char a, b;memset(arr, 0, sizeof arr);memset(eff, 0, sizeof eff);cin >> n >> s;while(n --){cin >> a;if(a == 'F'){cin >> b >> c >> d;if(arr[b - 'a'] && !ERR){cout << "ERR\n";ERR = 1; continue; //变量名重复} else {arr[b - 'a'] = 1;st.push(b); if(c == "n"){ c = "20000";}if(d == "n"){ d = "20000";}int C = stoi(c), D = stoi(d);if(D-C > 1000 && flag == -1){eff[b - 'a'] = 1; ++w;res = max(w, res);//判定复杂度} else if(C > D){flag = b; //废循环}}} else {if(st.empty()){if(! ERR){cout << "ERR\n"; ERR = 1;} continue;} int cur = st.top();st.pop();arr[cur - 'a'] = 0;if(flag == cur) { flag = -1; }if(eff[cur - 'a']) {eff[cur - 'a'] = 0;w --;}}}if(st.size()){while(st.size()){st.pop();}if(!ERR) {cout << "ERR\n";}continue;}if(s == "O(1)" && !ERR){if(res == 0) {cout << "Yes\n";} else {cout << "No\n";}} else if(!ERR){string s1;for(int i=4; i<s.size()-1; ++i){s1 += s.substr(i, 1);}if(stoi(s1) == res) {cout << "Yes\n";} else {cout << "No\n";}}}return 0;
}
http://www.wooajung.com/news/35416.html

相关文章:

  • Linux运行时so库的问题解决方案
  • HTML获取摄像头画面,拍照截图保存
  • 基于YOLOv8的交通车辆(12种常见车型)实时检测系统识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
  • 事倍功半是蠢蛋37 docker部分重启
  • ceph osd reweight-by-utilization 参数解析
  • 52.java语言程序 设计
  • 排查和解决服务器cpu过载的问题
  • C. Not Assigning
  • 基于运维编排实现服务器故障自愈
  • 49.底层逻辑
  • 28-48.雪中捍刀行
  • K8s Pod 多种数据存储方式
  • 14Java基础之抽象类、接口
  • 深入解析:mac电脑安装 nvm 报错如何解决
  • 洛谷 P12078 [OOI 2025] Best Runner 题解
  • 远程git ssh配置1
  • 7月24日总结
  • VIRTUBOX BUG
  • 精通Python PDF裁剪:从入门到专业的三重境界
  • 如何在群晖虚拟机快速部署线上web网站并实现公网访问
  • 向他人分享我的音频
  • - BigBosscyb - 博客园
  • 整体二分
  • 闲来无事
  • - daydreamer_zcxnb - 博客园
  • - Redamancy_Lydic - 博客园
  • - darling331 - 博客园
  • - kintsgi - 博客园
  • TIM外部中断
  • LPC总线设计及其仿真验证