学做游戏 网站,黄岛网站建设服务,天津网站建站公司,宁波外贸公司排名前五十必须强调下#xff0c;以下的任意一种优化#xff0c;都应该是在本身采用的算法没有任何问题情况下的“锦上添花”#xff0c;而不是“雪中送炭”。 如果下面的说法存在误导#xff0c;请专业大佬评论指正
读写优化
C读写优化——解除流绑定
在ACM里#xff0c;经常出现…必须强调下以下的任意一种优化都应该是在本身采用的算法没有任何问题情况下的“锦上添花”而不是“雪中送炭”。 如果下面的说法存在误导请专业大佬评论指正
读写优化
C读写优化——解除流绑定
在ACM里经常出现数据集超大造成 cin TLE的情况其实cin效率之所以低不是比C低级而是因为需要与scanf的缓冲区同步导致效率降低而且是C为了兼容C而采取的保守措施。 C代码中添加 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);这一段之后读取速度即可无限趋近于scanf和printf。 如果代码首部没有using namespace std; 则要换成std::ios::sync_with_stdio(0),std::cin.tie(0),std::cout.tie(0);
#include bits/stdc.h
using namespace std;int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);// 未使用using namespace std;时使用下方写法// std::ios::sync_with_stdio(0),std::cin.tie(0),std::cout.tie(0);// 代码主体读取、操作、打印
}std::ios::sync_with_stdio(0)
在 C 中取消同步流std::ios::sync_with_stdio是一个常用的技巧用来加快输入/输出流I/O的速度。默认情况下C 的标准库iostream与 C 的标准库stdio之间是同步的这意味着它们共享缓冲区并且每次使用其中一个库的 I/O 功能时都会刷新另一个库的缓冲区。这保证了数据的一致性但也增加了性能开销。
通过调用 std::ios::sync_with_stdio(0)你可以取消这种同步这通常会导致 I/O 操作的速度显著提高。但是一旦取消了同步就不能再混用 C 和 C 的 I/O 函数如 cin/cout 和 scanf/printf因为这可能会导致输出顺序不确定或其他问题。 如果已经采用了C的输入函数cin,就避免再使用C的scanf同样的如果已经使用 cout 就避免再使用 printf cin.tie(0)
在默认的情况下cin绑定的是cout每次执行的时候都要调用flush这样会增加IO负担。 这行代码解除了 cin输入流与 cout输出流之间的绑定。默认情况下cin 与 cout 绑定在一起这意味着在每次从 cin 读取之前cout 的缓冲区都会被自动刷新。通过解除绑定可以进一步提高 I/O 性能但这也意味着在输出和输入操作之间不再自动刷新 cout 的缓冲区。
cout.tie(0)
这行代码通常不是必须的因为 cout 默认情况下并不绑定到其他流。它的主要作用是确保 cout 不与任何其他流例如 cin 或 cerr绑定。但在大多数情况下这行代码并不会改变默认行为。
C换行输出
endl会输出’\n’\n是转义字符代表换行然后立即刷新缓冲区并输出到屏幕上。由于要刷新缓冲区endl会比\n慢一点一般不建议使用。以下是endl实现
template class _CharT, class _Traits
inline _LIBCPP_INLINE_VISIBILITY
basic_ostream_CharT, _Traits
endl(basic_ostream_CharT, _Traits __os)
{__os.put(__os.widen(\n));__os.flush();return __os;
}C中换行大多喜欢写 cout endl;然而据acmer和本人赛场亲身经历这种写法比 cout \n; 输出速度要慢许多。当然这不乏出题人的原因不过为了避免悲剧的发生希望大家还是使用如下两种方法。
在代码头部使用宏定义#define endl \n 替换endl改掉使用endl的习惯
#include bits/stdc.h
#define endl \nint main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);// 上方使用了宏定义,代码编译预处理阶段就将endl换成了\ncout endl;// 直接输出\ncout \n;
}C/C自定义快读快写
本人没有亲自使用过不过是看别人代码中有如此运用。据说C17后getchar()/putchar()已经被负优化了未知真假个人选择使用。
inline int read()
{int x0,f1;char chgetchar();while(ch0||ch9){if(ch-)f-1;chgetchar();}while(ch0ch9){x(x1)(x3)(ch^48);chgetchar();}return x*f;
}inline void write(int x)
{char F[200];int tmpx0?x:-x;if(x0)putchar(-);int cnt0;while(tmp0){F[cnt]tmp%100;tmp/10;}while(cnt0)putchar(F[--cnt]);
}Java快读快写
大部分初学Java的人应该是使用如下代码进行Java的读写不过下面这个代码的读写在面对大量数据的情况下是比较慢的。
import java.util.Scanner;public class Main {public static void main(String[] args) {// java.util 包下的读取Scanner sc new Scanner(System.in);int n sc.nextInt();// JavaSystem.out.println(n);sc.close();}
}下方的读写代码速度较快经过实践检验建议采用。该部分代码经过真实调试应该是不存在什么问题。 特别提醒如果使用了下方代码中的快速输出代码最后必须使用out.flush(); 必须使用out.flush(); 必须使用out.flush();
快速读入的代码按需使用写代码时不一定要全部写如果在XCPC赛场上使用Java可以提前写好该模板。
import java.io.*;/*** 自定义快读类*/
class Scanner {static StreamTokenizer st new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));// 字符串快速读入对象static BufferedReader br new BufferedReader(new InputStreamReader(System.in));public int nextInt() {try {st.nextToken();return (int) st.nval;} catch (IOException e) {throw new RuntimeException(e);}}public double nextDouble() {try {st.nextToken();} catch (IOException e) {throw new RuntimeException(e);}return st.nval;}public float nextFloat() {try {st.nextToken();} catch (IOException e) {throw new RuntimeException(e);}return (float) st.nval;}public long nextLong() {try {st.nextToken();} catch (IOException e) {throw new RuntimeException(e);}return (long) st.nval;}public String next() {try {st.nextToken();} catch (IOException e) {throw new RuntimeException(e);}return st.sval;}// 按行读入字符串public String readLine() {String s null;try {s br.readLine();} catch (IOException e) {e.printStackTrace();}return s;}
}
public class Main {// 快速输出对象static PrintWriter out new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));public static void main(String[] args) {// 创建自定义的Scanner类Scanner sc new Scanner();/*** 快读使用案例*/int n sc.nextInt();double d sc.nextDouble();float f sc.nextFloat();// 读入字符串(以空格、回车结尾)String str sc.next();// 整行读入字符串(以回车换行结尾)String line sc.readLine();/*** 快速输出使用案例*/out.println(n);out.println(d);out.println(f);out.println(str);out.println(line);// 快速输出必须要刷新缓冲区,否则无法输出out.flush();}
}读写样例
其他玄学优化——自行试用
下方玄学只是部分传言有些优化的效果似乎并不显著;有时不妨一试。
常用函数优化
inline int abs(int x)
{int yx31;return (xy)^y;
}
inline int max(int x,int y)
{int m(x-y)31;return (ym)|(x~m);
}
inline int min(int x,int y)
{int m(x-y)31;return (ym|x~m)^(x^y);
}
inline void swap(int x,int y)
{x^y,y^x,x^y;
}
inline int ave(int x,int y)
{return (xy)((x^y)1);
}变量自增
i快于i用减法代替取模运算
把函数中的循环变量在整个函数开头用register统一定义好
频繁使用的数用register和inline一个用法只不过有可能把变量存入CPU寄存器来减少时间;某些生命周期不重叠的变量合并减少创建变量空间的时间。
int main()
{register int i;for (i 1; i n; i){// 逻辑部分}for (i 1; i n; i){// 逻辑部分}/*下方循环多次使用i*/
}减少使用STL他们的常数特别大
现在大部分OJ平台都会自动开O2优化所以可能STL常数问题可能也没那么严重有时候也可以尝试手动开O2优化。据说有些时候可能会出现stl的map反而比自己手写map还快的情况…所以自己看情况吧
// 代码头部预处理指令手动打开O2
#pragma GCC optimize(2)define比赋值更快
定义数组大小时尽量用奇数
尽量不要用bool,int型比bool快
if()else() 语句比三元运算符慢;但if语句比三元运算符快
学会合理使用位运算
判奇偶性n1相当于n%21。交换变量x与y
inline void swap(int x,int y)
{x^y^x^y;
}