三、关于细节的小技巧

三、关于细节的小技巧

1.C++的IO效率低下?

关于IO(输入输出),大家普遍认为,

  • - cin/cout形式简单,适合新手,但效率不够。
  • - 卡时间的题目最好用scanf()/printf(),效率可以的。
  • - 毒瘤题目,就该自己写快读快写了。

不!前两句骗人的!只要有这三句话:

ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);

无需解释,只是取消绑定stdio,是cin/cout为了兼容C的scanf()/printf()的下策。

使用后,cin/cout解除了stdio的累赘,速度快如scanf()/printf()!

提示:为了方便,此文章的演示暂时不用这三行。

2.for循环还能优化?

for(int i = 1; i <= n; i++)//i可以取各种整形,这里用int

乍一看没啥毛病,贼完美的

小讲解一下自加自减运算符吧!

++i/–i 不会产生一个临时的空间,且速度稍快于i++/i–

如果数据量很大且题目很卡时间,那么for循环可以这么写

for(register int i = 1; i <= n; ++i)//具体写法因题目而异

3.O1/O2/O3优化可以手动开启?

没啥,我们不必依赖某些OJ的O2优化。我们可以手动开启。

O1

#pragma GCC optimize(1)
//O1(O)优化会减少一些编译时间,优化分支、常量表达式。

O2

#pragma GCC optimize(2)
//寄存器优化,占用编译时间与空间,减少更多运行时间和空间。在OJ上提交时编译时间不算在运行时间内。

O3

#pragma GCC optimize(3)
//就是升级版O2
或者
#pragma GCC optimize(3,"Ofast","inline")

注意!!!

这只能在OJ上玩玩而已,真正竞赛,用了不给分。所以,你要是真是竞赛开了O2之类,然后爆零,别怪我没提醒过你

3.memset咋用?

memset函数有时候很简单的。但是非多组输入时,memset(a, 0, sizeof(a))的写法没啥用。因为全局变量初值为0,而且我们还可以用int a = {0}int a = {}的方式赋值

举个栗子:

#include <bits/stdc++.h>
using namespace std;
int a[1005];
int main()
{
   int b[1005] = {0};
   int c[1005];
   memset(c, 0, sizeof(c));
   for(int i = 0; i < 1005; ++i)
      cout << a[i] << ' ' << b[i] << ' ' << c[i] << endl;
   return 0;
}

我们会惊奇地发现:

挖藕!都赋值成0了!

挖藕

当然,将数组赋值为 − 1 0 x 3 f 3 f 3 f 3 f -1 \quad0x3f3f3f3f 10x3f3f3f3f时必须用到memset

但是,你认为赋值为其他数就要开for循环吗?

不一定。介绍一下memset()&fill()的区别

memset()

是把一个数组的各字节(注意,不是元素)赋值。

一个int包含4个字节,而0和-1的二进制形式分别是全是0都是1

所以一个字节的0和-1的二进制形式分别是0000 00001111 1111

而0x3f3f3f3f(常用于表示无穷大)的每个字节都是0x3f,不正经的二进制形式是

0x3f 0x3f 0x3f 0x3f//没见过二进制字节中带有16进制的

好吧,这只是个演示,所以就可以

memset(a, 0, sizeof(a));    //赋值为0
memset(b, -1, sizeof(a));   //赋值为-1
memset(c, 0x3f, sizeof(a)); //赋值为0x3f3f3f3f(无穷大)

但是其他大部分常用数的几个字节是不全相同的,不能用memset.

fill()

是把一个数组的各元素赋值。

int arr[MAXN];//先不告诉你有多少个元素
const int num = 3;
fill(arr, arr + MAXN, num);
//等价于下面
for(int i = 0; i < sizeof(arr) / sizeof(int); ++i)//中间那个就是arr的元素数
	arr[i] = num;

fill还可以用于vector,如:

fill(v.being(), v.end(), 2);

为了代码简洁,有些人不用for循环赋值,而使用fill().

头文件

#include <cstring>//memset()
#include <algorithm>//fill()

4.稳定排序需要自己写归并吗?

不需要。algorithm包含stable_sort()稳定排序函数。用法与sort快排一样。

如果你忘了sort的用法,请回顾一哈:排序100个数据,稳定和不稳定排序

#include <algorithm>//for sort() and stale_sort
#include <iostream>
using namespace std;
int a[103], b[103];
int main()
{
    for(int i = 0; i < 100; ++i)
   		cin >> a[i] >> b[i];
    sort(a, a + 100);
    stable_sort(a, a + 100);
    for(int i = 0; i < 100; ++i)
        cout << a[i] << ' ' << b[i] << endl;
    return 0;
}

5.DEBUG为什么很费劲?

(1)代码规范

这可能是因为你的代码不够规范。现在的代码规范,基本要求是运算符之间要有空格,代码段之间要有空行,大括号要有层次缩进。拿上面的代码举栗子:

#include <algorithm>//规范代码
#include <iostream>//导入头文件

using namespace std;//使用命名空间

int a[103], b[103];//定义全局变量

int main()
{
    for(int i = 0; i < 100; ++i)
   		cin >> a[i] >> b[i];  //数据的输入
    
    sort(a, a + 100);		  //函数的调用和数据的操作
    stable_sort(a, a + 100);
    
    for(int i = 0; i < 100; ++i)
        cout << a[i] << ' ' << b[i] << endl;//数据的输出
    return 0;
}//清晰明了

再对比一下不规范的代码:

#include<algorithm>//不规范代码
#include<iostream>//没有空行
using namespace std;
int a[103],b[103];
int main()
{
for(int i=0;i<100;++i)//没有缩进
cin>>a[i]>>b[i];//没有空格
sort(a,a+100);
stable_sort(a,a+100);
for(int i=0;i<100;++i)
cout<<a[i]<<' '<<b[i]<<endl;
return 0;
}//代码一长,脑袋都疼

(2)输出数据

也可以把用到的数据输出一下。//没错,就这么简单

这就是C++程序的小技巧,大家都学会了吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值