最后更新:2019/08/06
程序 d e b u g debug debug 的时候,一遍又一遍地复制样例是很痛苦的事情,特别是机房里的 w i n 7 win7 win7 系统还不能右键粘贴。因此一般我们会利用读文件的方式减少在复制粘贴样例上的用时。例如这样:
int main(){
freopen("test.in", "r", stdin);
freopen("text.out", "w", stdout);
return 0;
}
当然,上面的代码十分的差,因为提交的时候需要到程序中寻找语句并且删除,和复制样例比起来感觉还麻烦了不少,因此我们可以在本地定义一个符号,最终提交的时候删掉头上的定义即可:
#define LOCAL
int main(){
#ifdef LOCAL
freopen("test.in", "r", stdin);
freopen("text.out", "w", stdout);
#endif //LOCAL
return 0;
}
但是在比赛中由于紧张而忘记删除语句的现象频频发生, W r o n g Wrong Wrong A n s w e r Answer Answer 的罚时是吃不起的,因此我们需要的是一种能够在本地调试和提交时自适应的代码。
然而定义符号的方式有很多,其中一种是在编译选项中加上 - D L O C A L DLOCAL DLOCAL ,这种在 I D E IDE IDE 内部定义符号的方式满足了我们的需求。(自然 L O C A L LOCAL LOCAL 也可以换成别的符号,看需求)
由于笔者用的是 D E V DEV DEV C C C++,下面给出的是 D E V DEV DEV C C C++ 的编译选项设置方式:
工具->编译选项->编译器->编译时加入下列指令[√]
在这里加入 - D L O C A L DLOCAL DLOCAL ,并勾选编译时加入指令。
然后在编写程序时就可以放心使用文件了,因为就算不删除那些代码, O J OJ OJ 上的编译器由于没有 L O C A L LOCAL LOCAL 符号,会在编译阶段忽略掉这些语句。
2019/7/20更新:
在 C l i o n Clion Clion 下加入编译选项的步骤是:
打开工作区的CMakeLists.txt,加入add_definitions(-DLOCAL),reload changes
最终模板如下:
#include
using namespace std;
int main(){
#ifdef LOCAL
freopen("test.in", "r", stdin);
freopen("text.out", "w", stdout);
#endif //LOCAL
return 0;
}
在 A C M ACM ACM 里,经常出现数据集超大造成 c i n cin cin T L E TLE TLE 的情况。(以前碰到 c i n cin cin T L E TLE TLE 的时候总是傻乎乎地改成 s c a n f scanf scanf )这时候大部分人(包括原来我也是)认为这是 c i n cin cin 的效率不及 s c a n f scanf scanf 的错,甚至还上升到 C C C 和 C C C++ 的执行效率层面的无聊争论。然而这只是C++为了兼容而采取的保守措施。真实效率 c i n cin cin 和 s c a n f scanf scanf 是差不多的。(现在写的代码要是效率打不过以前的代码可就真丢人了)
我们可以在 I O IO IO 之前将 s t d i o stdio stdio 解除绑定,方法很简单,只需要在代码里加入一行:
std::ios::sync_with_stdio(false);
这个函数是一个「是否兼容 s t d i o stdio stdio」的开关, C C C++ 为了兼容 C C C ,保证程序在使用了 s t d : : p r i n t f std::printf std::printf 和 s t d : : c o u t std::cout std::cout 的时候不发生混乱,将输出流绑到了一起。
但是一定要注意,**用了这个语句之后不能再混用 p r i n t f printf printf 和 c o u t cout cout 或是混用 s c a n f scanf scanf 和 c i n cin cin **。
2019/8/6更新:
当然,有些毒瘤题是真的能卡时间……在这种情况下快读就应运而生:
template<typename T>
inline T read() {
T x = 0, s = 1;
char ch = getchar();
while (ch <= '0' || ch > '9') { if (ch == '-') s = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return x * s;
}
或者可以这样,我更倾向于使用这种:
template<typename T>
inline void read(T &x) {
int s = 1; x = 0;
char ch = getchar();
while (ch <= '0' || ch > '9') { if (ch == '-') s = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
x *= s;
}
template<typename T, typename... Args>
inline void read(T &x, Args &... args) {
read(x);
read(args...);
}
一般来说用了快读就不会去用别的读入方式,再加上题目一般给的都是整数……基本能解决由于读入大数据引起的问题。当然,这个读入方式还是不够快——虽然比 s c a n f scanf scanf 快多了,但是 g e t c h a r ( ) getchar() getchar() 本身还是封装过的,可以考虑通过手写 g e t c h a r getchar getchar 来进一步加快读入速度。
在学习数据结构时,算法的用时就是算法的好坏,但是在比较算法好坏的时候又遇到了困难:我怎么知道这个算法用时多少呢?
#include
#include
const int maxk = 1e5;
//按照实际数据量修改
//算法竞赛中一般认为1s可以做10^8次操作
clock_t start, stop;
double duration;
int main()
{
//处理数据输入
start = clock();
for(int i=0; i<maxk; i++) //如果数据量过小可以用循环放大时间
{
//运行算法
}
stop = clock();
duration = ((double)(stop - start))/CLOCKS_PER_SEC;
//也有写成CLK_TCK的,但是这是二次宏定义的结果,底层是CLOCKS_PER_SEC
printf("ticks = %f\n", (double)(stop-start));
printf("duration = %6.2e\n", duration);
return 0;
}