竞赛代码相关技巧

最后更新: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<bits/stdc++.h>
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<cstdio>
#include<ctime>
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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值