首页 > 编程语言 >C++竞赛优化技巧与考场实用技巧

C++竞赛优化技巧与考场实用技巧

时间:2024-07-17 18:57:59浏览次数:14  
标签:实用技巧 10 int 复杂度 C++ 考场 使用 优化 define

在洛谷观看更加简约哦~:一键直达

距离 2024 CSP/NOIP 已经不远了,在这里,我便分享一下我总结出来的竞赛优化技巧

时间优化

算法/数据结构优化

在处理一些问题,我们可以采用更高效的算法/数据结构来代替低效的算法/数据结构。

例如,你需要多次求一段区间的和时,一般会采用循环直接累加,那么时间复杂度就是 O(N) 。但是如果你采用线段树来解决这个问题,那么时间复杂度就可以降到 O(logN) ,这是质的转变。

再举一个平常的例子,排序,最开始大家学的都是冒泡排序,插入排序。这些排序的时间复杂度为 O(N^2) 。而大家熟知的快排平均时间复杂度为 O(NlogN) 极端情况下为 O(N^2) 。再如桶排序,一般时间复杂度为 O(N)极端情况下时间复杂度为 O(NlogN) $。可以直观的发现不同算法的时间复杂度差异。

除此之外还有查找操作,哈希表比线性搜索更快;频繁插入和删除元素,链表更好等,这里就不再展开了。

输入输出优化

输入优化

在c++中拥有非常多的输入方式,而一般我们使用的输入输出语句,由于设计与安全上的原因,时间复杂度可能会偏高,一般来说,当输入的数据个数超过 $ 10^6 $ 时,如果使用 cin/scanf 语句就会有超时的风险,这时我们可以采用以下方法:

方法1

使用 cin/cout 语句时,我们可以使用以下语句来关闭流同步,加快输入输出速度。

ios::sync_with_stdio(0);
cin.tie(0);
方法2

在 C++ 中读入字符的效率是高于读入整型变量的,所以可以采用读入字符的方式来读入整数。代码如下:

int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}

输出优化

与快读一样,也是将整数拆解为字符的形式输出,代码如下:

void write(int x)
{
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
    return;
}

输出的优化除了快写优化以外,还有一点非常重要,那便是换行方式,一般初学者会使用 endl 来进行换行,但是 endl 效率较低,遇到输出数量大的问题时容易超时,一般我们使用 C语言中的 “\n” 进行换行,用法如下:

cout<<"星月666"<<"\n";
cout<<"星月999\n";
printf("星月awa\n");

其他

namespace FastIO
{
	#define FS 100000
	#define Tp template<typename Ty>
	#define Ts template<typename Ty,typename... Ar>
	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
	#define D isdigit(oc=tc())
	int ff,OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
	void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}struct IO_Cl {~IO_Cl() {clear();}}CL;
	Tp void read(Ty& x) {x=0,ff=1;while(!D) ff=oc^'-'?1:-1;while(x=(x<<3)+(x<<1)+(oc&15),D);x*=ff;}
	Ts void read(Ty& x,Ar&... y) {read(x),read(y...);}
	Tp void write(Ty x) {while(OS[++OT]=x%10+48,x/=10);while(OT) pc(OS[OT--]);}
	Tp void writeln(Ty x) {write(x),pc('\n');} 
	#undef D
}using namespace FastIO;

//使用示例:read(n,m), read(a[i]), writeln(ans)

机房大佬发的,需要配合 freopen 使用,自己本地编译时无法使用,一般可以在最后加。直接当成函数使用即可,有知道原理的大佬可以私信解释一下(我太菜了)

缓存优化

图的存贮

如果需要保存第 i i i 条边的多个信息时,使用结构体优于使用多个数组存贮,具体使用如下:

//较快
struct node{
	int u,v,w;
}a[100005];
//较慢
const int N=1e5+5;
int u[N],v[N],w[N];

分块离线

对于分块查询等问题,可以将每次查询头尾的块内查询离线下来,可以显著提升程序运行效率。

常数优化

通常来说,乘法慢于加减法,位运算与加减法差不多,除法则远慢于乘法。

STL优化

结论(摘自进阶篇)

  • STL中通常只有数据结构需要担心性能,sort 等函数性能一般非常优秀,只要不遇到特(du)殊(liu)的数据一般没事,而数据结构,在开启了 O 2 O2 O2 优化后性能有显著提升。

  • list 性能很差,而且不能满足竞赛中的各种需要,推荐手写链表。

  • deque 和基于其的 stack,queue 性能较差,如果数据量大尽量避免使用,可使用固定大小的数组替代。

  • set,map 功能强大,但新能一般,可以使用 离散化等离线技巧代替。

  • unordered_mapmap 好,但不是很快,可以手写哈希表来代替,可大幅度改善性能。

时间优化总结

实践出真知,刷题量成就大牛。

空间优化

算法

减少 dfs 的使用,dfs使用时会调用栈,占用额外的内存。

数据结构

使用合适的数据结构可以大幅度减小空间的浪费。例如使用哈希表不仅可以节省时间还可以节省空间。

遇到一些数据范围很大,但是数据分布很散的题目,可以使用离散化来减小空间的浪费

其他

尽量减少临时变量的创建,多次利用可利用的临时变量

实用技巧

对拍

随机数据生成

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10000000
int main()
{
	//freopen(".in","r",stdin);
	freopen("data.out","w",stdout);
	mt19937 Rand(time(0));//生成随机种子 在random头文件中 
	cout<<Rand() %MAXN<<" "<<Rand()% MAXN;
	return 0;
}

文件比对(windows)

1.打开 cmd (Win+R 输入 cmd 即可打开)

2.输入 cd /d (文件夹目录地址 例:C:\Users\qzez\Desktop\)这是桌面地址

具体格式: cd /d C:\Users\qzez\Desktop\ 即可切换到桌面

3.比较 :fc 文件名1 文件名2

如果提示 无法打开 - 找不到此类文件或文件夹

请检查以下是否打开了文件扩展名。

文件比对(Linux)

1.打开 bash (不会请百度)

2.输入 cd 目录名 (与windows相同)

3.比较:diff 文件1 文件2

考场注意事项

1.进入考场先试机!否则如果没关还原保护的话,关机就爆零两行泪了!

2.比赛时遇到多组数据一定要记得清零。

3.比赛结束前10分钟不要写代码了,检查一下 freopen

4.先看一遍题目,防止错过总司令,然后先把所有暴力分拿下,不仅时为了最后没时间最准备,也为对拍做了准备。

5.试机结束以后,先把快读,线段树等模板打好,防止比赛时心急遗忘。

6.检查电脑上有无计算器,Excel,画图等实用软件。

7.如果使用了 #define int long long 别忘了看一下 scanfprintf 里面有没有改为 lld ! 本人吃过亏…

误区

众所周知,CCF的评测机如今已经开启了 O2 优化,所以以前的一些优化,在打开了 O2 优化之后,可以不再使用

-尽量不要使用 intline ,因为其通常会被忽略,有时甚至会降低程序效率,如果你想要强制内联,推荐使用 #define

-尽量不要使用 register,在 C++11 其已经被废弃,在 C++17 中,其已经被禁止。

  • 没有必要将 x * 10 写为 (x << 3) + (x << 1)

  • 对于整数来说,没有必要将 i++ 写为 ++i

  • 没有必要可以规避高维数组(空间允许的情况下)

总结

编程是练出来的,不是听/看出来的,大家要多刷题,多练习,多比赛增加实战经验。

祝大家 CSP/NOIP 2024 RP++。

本文因为时间仓促,有许多细节之处尚未完善,请诸位OIER踊跃提出,帮助本文更加完善!

本文有很多内容参考了洛谷出品的深入浅出进阶篇,推荐大家看一看,书中内容更加丰富。

参考 & 鸣谢:

深入浅出进阶篇(洛谷教研组出品)

Csdn文献资料

星月工作室洛谷团队全体成员

yummy提出格式修改建议

lzm0107提出生成随机数据代码的建议

标签:实用技巧,10,int,复杂度,C++,考场,使用,优化,define
From: https://blog.csdn.net/daihaoweikevin/article/details/140470181

相关文章

  • 2024年华为OD机试真题-图像物体的边界-C++-OD统一考试(C卷D卷)
     2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集)题目描述:给定一个二维数组M行N列,二维数组里的数字代表图片的像素,为了简化问题,仅包含像素1和5两种像素,每种像素代表一个物体,2个物体相邻的格子为边界,求像素1代表的物体的边界个数。像素1代表的......
  • Visual Studio 2022下载安装教程c++
    文章目录VisualStudio安装教程一、官网下载二、安装三、配置四、VisualStudio2022使用教程VisualStudio安装教程一、官网下载下载地址:https://visualstudio.microsoft.com/zh-hans/downloads/二、安装要是个人学习的活就下载社区版下载完成后是一个安......
  • C++ 智能指针类型转换测试
    这个是GPT回答的,可以运行。#include<iostream>#include<memory>classBase{public:virtualvoidshow()const{std::cout<<"Baseclass"<<std::endl;}virtual~Base()=default;//确保基类有虚析构函数};classDe......
  • 图解C++中的寻址。指针常量,常量指针。const int *p ,int * const p
    输出方式1.直接输出——采用直接寻址,输出内存块中的操作数,变量值变量名代替地址,容易记忆。intmain(){inta=10;//a=0x99fdcout<<a<<endl;//10,输出时系统采用直接寻址,输出a地址中存储的操作数return0;}2.取地址,&a——输出地址intmain()......
  • C++ 《运算符重载》
    示例代码#include"iostream"//operator+usingnamespacestd;classA{public:intm_age;public:A(){}A(intage):m_age(age){}//Aoperator+(constA&a){//成员函数实现重载//Atemp(0);//temp.m_age=m_age+a.m_age;//......
  • c/c++ 浅拷贝与深拷贝
    浅拷贝与深拷贝的区别浅拷贝:简单的赋值拷贝操作深拷贝:在堆区重新申请空间,进行拷贝操作默认情况下对象拷贝是浅拷贝(深拷贝要自己实现拷贝函数)classPerson{public: //无参(默认)构造函数 Person(){ cout<<"无参构造函数!"<<endl; } //有参构造函数 Person(in......
  • 高质量C/C++编程指南总结(七)—— 内存管理
    1.内存分配的方式从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处......
  • C++扫雷小代码
    先声明一下:玩法介绍程序会提示输入:<ROW><COL><HEALTH><MINE_SUM>,分别代表行数,列数(均小于等于30),生命值(小于行数×列数),雷数(小于行数×列数),有数据判断操作符qpca+X,Y分别代表:在(x,y)²(见注释)翻开/插旗/撤销插旗/使用Ai(作为起始点)³,以下为详细介绍qxy:翻开位于......
  • 二叉苹果树(C++)
    【题目描述】有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共 N 个节点,标号1 至 N ,树根编号一定为 1 。我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹......
  • 小球掉落(C++)
    #include<bits/stdc++.h>usingnamespacestd;structnode{ intid; booldata; intfather; intlson,rson;};nodetree[6000000];intd,i;intmain(){ cin>>d>>i; tree[1].father=0; tree[1].lson=2; tree[1].rson=3; tree[1].data=false;......