Fast I/O C++ 快速输入/输出

index > Misc > Fast I/O


基本习惯

  1. 尽量printf /scanf

  2. cin /cout 的时候记得关同步

        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
  3. 关同步的cin /cout 不要和printf /scanf混用。

  4. 注意endl自带了fflush,输出较慢。

虽然不一定很快,但是一般能过。

卡过时限——读入挂

有时候对自己的算法很有信心,觉得读入再快一点就肯定能过了。

于是就有人发明了各种各样的读入挂 ,但很少派上用场

我就存了一个最可能用到,也比较好敲的读入挂。(尤其是现场赛的时候)

template <typename _Tp> inline _Tp read(_Tp&x){
   
    char c11=getchar(),ob=0;x=0;
    while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}

对于整数类型的变量a,直接写read(a)就行了。这也是常见的优化思路之一,通过读char来加速读入。

极致速度——现场绝缘

下面的轮子来自Fast and furious C++ I/O 可以从这里拷贝到,洋洋洒洒500多行,既然牺牲代码长度(可复现性),那么就一定要有极致的速度啦。

使用方法:

首先在main的开头,或者宏定义的开头,需要做输入输出指向的配置。(下面的代码自己选择一个input和output放进自己代码即可)

#ifdef ONLINE_JUDGE
  input.reset(new InputFile(stdin, false));    // usual problem
  input.reset(new InputFile());                // interactive problem
  output.reset(new OutputFile());
#else
  input.reset(new InputFile());                // local testing using a console
  input.reset(new InputFile("input.txt"));     // local testing using a file
  output.reset(new OutputFile());              // output to console
  output.reset(new OutputFile("output.txt"));  // output to a file
#endif

然后你就可以在外挂下面写自己的实例,比如:

const int N = 1001;
int n, m;
char s[N][N];
int a[N], b[N];
 
int main() {
   
  input.reset(new InputFile(stdin, false));
  output.reset(new OutputFile());
 
  read(n, m, s, n, a, n, b, m);
  writeln(n, m, '\n', setDelimiter("\n"), s, n);
  writeln(setDelimiter(", "), a, n, '\n', b, m);
  return 0;
}

输入输出封装的都很完备,基本所有类型都支持(甚至std::string),在自己写的时候也会非常方便。

可以自己试试把原来的比较慢的代码加入这个黑科技来提交试试,体验愉悦。甚至会影响一个题的平衡,比如出题人不希望出现带log的做法,但被这个外挂优化过去了。

注* 我自己测试好像__int128是不行的。

#include <algorithm>
#include <cassert>
#include <complex>
#include <cstring>
#include <memory>
#include <string>
#include <vector>

using namespace std;

template <class T> struct is_iterator {
   
  template <class U, typename enable_if<!is_convertible<U, const char*>::value, int>::type = 0>
  constexpr static auto has_indirection(int) -> decltype(*declval<U>(), bool()) {
    return true; }
  template <class> constexpr static bool has_indirection(long) {
    return false; }
  constexpr static bool value = has_indirection<T>(0);
};

using uint = unsigned int;
// Buffer size should be 2^12 or 2^13 for optimal performance with files.
const uint BUFFER_SIZE = 1 << 12;
// Maximum possible length of a string representing primitive type
// assuming we won't encounter huge double values.
const uint MAX_LENGTH = 1 << 7;

namespace Detail {
   
  struct Width {
    uint value; };
  struct Fill {
    char value; };
  struct Base {
    uint value; };
  struct Precision {
    uint value; };
  struct Delimiter {
    const char* value; };
}  // namespace Detail

Detail::Width setWidth(uint value = 0) {
    return {
   value}; }
Detail::Fill setFill(char value = ' ') {
    return {
   value}; }
Detail::Base setBase(uint value = 10) {
    assert(2 <= value && value <= 36); return {
   value}; }
Detail::Precision setPrecision(uint value = 9) {
    assert(value < MAX_LENGTH); return {
   value}; }
Detail::Delimiter setDelimiter(const char* value = " ") {
    return {
   value}; }

/******************************* input classes ********************************/
class InputDevice {
   
protected:
  const char* head;
  const char* tail;

  InputDevice(const char* head, const char* tail) : head(head), tail(tail), base(setBase().value) {
   }

  virtual void fillInput() = 0;

  inline char nextChar() {
   
    if (__builtin_expect(head >= tail, false)) fillInput();
    return *head++;
  }

  template <class I> int readUnsignedIntGeneral(I& arg, char c) {
   
    I value = 0;
    int length = 0;
    for (;; ++length, c = nextChar()) {
   
      if (isDigit(c)) c -= '0';
      else if (isUpper(c)) c -= 'A' - 10;
      else if (isLower(c)) c -= 'a' - 10;
      else c = base;
      if (c >= base) break;
      value = base * value + c;
    }
    arg = value;
    return --head, length;
  }

  template <class I> inline int readUnsignedInt(I& arg, char c) {
   
    if (__builtin_expect(base > 10, false)) return readUnsignedIntGeneral(arg, c);
    I value = 0;
    int length = 0;
    for (; static_cast<unsigned char>(c - '0') < base; ++length, c = nextChar())
      value = base * value + c - '0';
    arg = value;
    return --head, length;
  }

  template <class I> inline bool readSignedInt(I& arg, char c) {
   
    bool negative = c == '-';
    if (negative) c = nextChar();
    typename make_unsigned<I>::type unsignedArg;
    if (readUnsignedInt(unsignedArg, c) == 0) return false;
    arg = negative ? ~static_cast<I>(unsignedArg - 1) : static_cast<I><
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值