OI and C++

1.结构体重载运算符

语法还债系列1

(一般用于结构体的优先队列)举例说:

1 struct SP{int value,node;};
2 bool operator <(SP a,SP b) 
3 {
4     return a.value>b.value;
5 }
6 priority_queue<SP> hp;

改变小于号对于结构体SP的定义,让value小的结构体的被认为是“大”,value大的结构体的被认为是“小”,从而以结构体中的value为关键字建立一个结构体小根堆

2.下标为负的问题

c++数据下标为负时运行会爆出一个数,但是不会RE,在做递推/dp时可能会把它当成正常的答案,调试时要注意~~(欢迎使用pascal)~~

3.传值,传引用,传指针

语法还债系列2

写这条的起因是在写 p1005 矩阵取数游戏 时,因为std::string的高精常数太大,被卡t了一个点。最后在两次共产主义支援下,成功不开O2不稳定地过掉了(参见“奇怪汇总”)。然而自己初学时对语法和原理接触甚少,于是亲身实验+百度研究了一下函数的各种传参。

参考&感谢

@communist

现在有一个函数f,用来解决NOIP2017d1t1— —喜闻乐见的小凯的疑惑,它长这个样子

1 long long f(long long na,long long nb)
2 {
3     na-=1,nb-=1;
4     long long c=na*nb-15     return c;
6 }

我们把它作为传值的例子,在主函数里这样写

1 balabalabala...
2 long long ans=f(a,b);
3 printf("%lld %lld %lld",ans,a,b);

输入3 7,输出11 3 7,原理大概是这样的:函数f从存储a的地址把a复制到na里,从存储a的地址把b复制到nb里,函数里关于na和nb的操作和a,b没有任何关系

接下来我们修改一下这个函数,改成传引用的形式

1 long long f(long long &na,long long &nb)
2 {
3     na-=1,nb-=1;
4     long long c=na*nb-15     return c;
6 }

输入3 7,输出11 2 6。原理大概是这样的:函数f通过传引用找到na和nb的地址,然后直接修改这里存储的内容(a和b),所以最后输出时a和b都减去了1

我们再把函数f修改一番,改成传指针

 1 long long f(long long *na,long long *nb)
 2 {
 3     *na-=1,*nb-=1;
 4     long long c=*na * *nb-1 5     return c;
 6 }
 7 ......
 8 balabalabala...
 9 long long ans=f(&a,&b);
10 printf("%lld %lld %lld",ans,a,b);

输入3 7,输出11 2 6。原理大概是这样的:我们把a和b的地址作为参数传入函数f,函数把它们当做指针,根据na和nb两个指针找到指向的内存开始修改内存里的数(a和b)(然而我平时并不用指针)

然而关于传引用的问题,还没有完,我们如果这样写

1 long long f(long long &na,long long &nb)
2 {
3     na-=1,nb-=1;
4     long long c=na*nb-15     return c;
6 }
7 balabalabala...
8 long long ans=f(a,7);
9 printf("%lld %lld %lld",ans,a,b);


就会喜闻乐见地CE掉。原因大概是这样的:我们直接把一个参数7塞进了函数里,而“7”这个常量没有所在的地址,函数也不可能“找到”,所以编译时会直接报错。如何解决呢?在传参数时用const修饰一下,就可以过了

1 long long f(const long long &na,const long long &nb)
2 {
3     na-=1,nb-=1;
4     long long c=na*nb-15     return c;
6 }
7 balabalabala...
8 long long ans=f(a,7);
9 printf("%lld %lld %lld",ans,a,b);

对于类似于stirng的自带大常数的stl,在传参数时可以传引用以提高效率(注意如果会传常量要加const修饰,然后不能修改了),经实验(不管加不加const)应该对运行速度是有提升的

计划外的发现:只加上const修饰(传值),(至少对于string这类)速度应该也比直接传值快

然而我还有一个问题:为什么const修饰后就可以对常量传引用了呢,常量应该根本没法引用啊?哪位神犇看到了麻烦告知,谢谢quq。

ask ask ask

4.常数优化

通用(*是感觉作用不大/据说有用的):

register

能const的const掉,用多次的先求出来

快读快输(必要的时候贴一个fread)

尽量用临时变量,访问快

浮点数乘整型的时候把整型写在前面

实数二分考虑限制次数

三元运算符*

inline*

++i换i++*

struct/string这种“笨重”的东西考虑传地址

尽量避免数组多次寻址(指高维数组)

memset/memcpy的$\frac{1}{32}$常数*

cmath相关函数比较慢,考虑预处理

手写排序(快排/归并)

尽量减少递归

减法取模,注意只适用于当前答案超出模数不多的情况

有符号换成无符号

特殊:

矩阵乘法 i->k->j

char转int 直接xor 48

线段树记录左右端点*

沙雕:

循 环 展 开 

松 松 松 排 序

指 令 集

---------------

睿智的蒟蒻yd提醒您:

卡常千万条,适度第一条

卡常不节制,亲人两行泪

6.常见各类型的变量的输入/输出及范围

语法还债系列3

int->%d----from $-2^{31}$ to $2^{31}$ $-1$ (<=$10^9$可用)(x10)

->%X(x16)

long long->%lld----from $-2^{63}$ to $2^{63}$ $-1$ (<=$10^{18}$可用)

unsigned long long->%ull----from $0$ to $2^{64}$ $-1$(<=$10^{19}$可用)

short->%hd----from $-2^{15}$ to $2^{15}$ $-1$(<=$10^4$可用)

double->%lf----整数部分+小数部分总计16位有效

long double->%Lf----经自己实验,纯整数/整数1位+小数总计18位有效;整数+小数似乎不稳定,但能保持在16位有效

7.DevC++的一些编译选项

①-Wall/-Wextra(显示最多警告/显示额外警告)

Tools->Compiler Options->Settings->Warnings->Show most warnings(-Wall)

②C++11 

Tools->Compiler Options->Settings->Code Generation->Language standard(-std)->GNU C++11

posted @ 2018-09-18 17:51  Speranza_Leaf  阅读(223)  评论(0)    收藏  举报