比赛时的小tips

文件输入输出的效率问题

请看本站的另一篇博文.在那篇博文中测试了各种读入的时间效率.传送门

读入优化

1
2
3
4
5
6
7
inline int read()
{
int x=0,p=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-')p=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*p;
}

数组的负数下标

定义一个数组指针在原数组的中间,对这个指针进行操作:

1
2
int a[100],*b=a+50;
b[-1]=1;//实际上也就相当于a[49]=1

内存占用过大?动态申请(非vector)

这个问题主要是针对有时候所开的空间太大,可能会导致爆空间.
这种不确定的情况下,我们就可以动态申请数组的空间.
而且这个动态申请是不同于我们平时所说的局部变量,那个是保存在栈里面,容易爆;这个动态申请使用的是堆空间,比那个不知道高到哪里去了:

1
2
3
4
5
6
7
8
int main(){
int n;
cin>>n;
int *p=new int[n];
for(int i=0;i!=n;++i)cin>>p[i];
for(int i=0;i!=n;++i)cout<<p[i]<<" ";
return 0;//*
}

数组的指针妙用

众所周知,数组名实际上就是指向该数组第一个元素的地址的一个指针.那么同理,&a[i]实际上也可以用a+i指代.
至于效率相差如何,尚未可知.用scanf输入的时候也就可以直接这么写:

1
scanf(""%d",a+i);

运算符的重载

像这样:

1
2
3
4
5
6
7
struct node
{
int x,p;
bool operator < (const node a)const{return x>a.x;}
node(int h,int h1){x=h;p=h1;}
};
priority_queue<node>q;//小根堆,以x排序

对拍

不得不说,对拍是一种非常好用的技巧,特别是在大型的OI竞赛中.
所谓对拍,其实就是为了检验自己的算法是否正确,将自己程序的输出跟一个绝对正确的暴力程序的输出进行对比.
我们需要写一个数据生成器(暂且命名为data.exe),自己的程序(a.exe),暴力程序(b.exe),然后通过批处理脚本进行对拍.

数据生成器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<windows.h>
int main()
{
Sleep(1000);//这里要注意一个细节,我们的随机数种子是根据当前时间来取,如果两次运行间隔时间太短会导致生成的数据相近(或者根本就是一样的),因此在程序运行时先Sleep个1秒.
freopen("a.in","w",stdout);
int n;
srand((int)time(0)); //调用srand()函数,以系统时间为随机种子
n = 1 + rand()%10000; //随机生成一个1到10000的自然数
printf("%dn",n); // 输出随机生成的自然数
return 0;
}

对拍文件,命名为*.bat,用任意的文本编辑器都可以进行编辑

1
2
3
4
5
6
7
8
9
@echo off
:start
gen.exe
type a.in
a.exe
b.exe
fc a.out b.out
if not ERRORLEVEL 1 goto :start
pause

显示 Gitment 评论