快读快写的艺术

2021~2022的老板子

快读

1.
inline int read() {
	register int x = 0, f = 1;
	register char ch = getchar();
	while (ch < '0' || ch > '9') {
		f = ch == '-' ? -1 : 1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = (x << 3) + (x << 1) + (ch ^ 48);
		ch = getchar();
	}
	return f == -1 ? -x : x;
}
2.
inline void read(int &x) {
	x = 0;
	register int f = 1;
	register char ch = getchar();
	while (ch < '0' || ch > '9') {
		f = ch == '-' ? -1 : 1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = (x << 3) + (x << 1) + (ch ^ 48);
		ch = getchar();
	}
	if (f == -1) x = x;
}
3.
//好像我忘记压行了,下面的
#define register re
template<typename Type> inline void Read(Type& Num) {
	re f = 1; re ch = getchar();
	while (ch < '0' || ch > '9') f = ch == '-' ? -1 : 1, ch = getchar();
	while (ch >= '0' && ch < '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	x = f == -1 ? -x : x;
}
4. 
template<typename _Tp> inline void read(_Tp&x) {
  register int f = 1; register char ch = getchar();
  for (; ch < 48 || ch > 57; ch = getchar()) f = ch == '-' ? -1 : 1;
  for (; ch >= 48 || ch <= 57; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
  x *= f;
}

快写

1.
inline void write(int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) write(x / 10);
	putchar(x % 10 + 48);
}
2.
template<typename _Tp> inline void write(_Tp x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) write(x / 10);
  putchar(x % 10 ^ 48);
}

快读原理

很水, 就是每次输入的时候根据他的ASCII码进行转化
可能有人会觉得

x = (x << 3) + (x << 1) + (ch ^ 48);

十分的玄学,其实很水
根据位置原理, n o w = 10 n o w + s t r i ( t o   i n t ) now = 10now + str_i(to\ int) now=10now+stri(to int)
说的简单点说,就是 66 = 6 × 10 + 6 66 = 6\times 10 + 6 66=6×10+6
x < < i 等价于 x × 2 i x << i 等价于 x \times 2^i x<<i等价于x×2i位运算他更快它更香(你快读快写本来就是用来卡常的,怎么快怎么来)

快写

相当于一个栈, 每次write()下一个都压入一个数字,然后最后他是从下到上的输出的
typedef register jiandan
typedef int cubao
jiandan cubao


Update 4/3 2022

这里有一份HE的板子,加速版

struct Scanner {
  FILE* fp = nullptr;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;
  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\0';
  }
  bool succ() {
    while (true) {
      if (st == ed) {
        reread();
        if (st == ed) return false;
      }
      while (st != ed && isspace(line[st])) ++st;
      if (st != ed) break;
    }
    if (ed - st <= 50) reread();
    return true;
  }
  template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
  bool read_single(T& ref) {
    if (!succ()) return false;
    while (true) {
      size_t sz = 0;
      while (st + sz < ed && !isspace(line[st + sz])) ++sz;
      ref.append(line + st, sz);
      st += sz;
      if (!sz || st != ed) break;
      reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  bool read_single(T& ref) {
    if (!succ()) return false;
    bool neg = false;
    if (line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while (isdigit(line[st])) {
      ref = 10 * ref + (line[st++] - '0');
    }
    if (neg) ref = -ref;
    return true;
  }
  template <class T>
  bool read_single(vector<T>& ref) {
    for (auto& d : ref) {
      if (!read_single(d)) return false;
    }
    return true;
  }
  void read() {}
  template <class H, class... T>
  void read(H& h, T&... t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }
  Scanner(FILE* _fp) : fp(_fp) {}
};
struct Printer {
 public:
  template <bool F = false>
  void write() {}
  template <bool F = false, class H, class... T>
  void write(const H& h, const T&... t) {
    if (F) write_single(' ');
    write_single(h);
    write<true>(t...);
  }
  template <class... T>
  void writeln(const T&... t) {
    write(t...);
    write_single('\n');
  }
  Printer(FILE* _fp) : fp(_fp) {}
  ~Printer() { flush(); }

 private:
  static constexpr size_t SIZE = 1 << 15;
  FILE* fp;
  char line[SIZE], small[50];
  size_t pos = 0;
  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }
  void write_single(const char& val) {
    if (pos == SIZE) flush();
    line[pos++] = val;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  void write_single(T val) {
    if (pos > (1 << 15) - 50) flush();
    if (val == 0) {
      write_single('0');
      return;
    }
    if (val < 0) {
      write_single('-');
      val = -val;
    }
    size_t len = 0;
    while (val) {
      small[len++] = char('0' + (val % 10));
      val /= 10;
    }
    for (size_t i = 0; i < len; ++i) {
      line[pos + i] = small[len - 1 - i];
    }
    pos += len;
  }
  void write_single(const string& s) {
    for (char c : s) write_single(c);
  }
  void write_single(const char* s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; ++i) write_single(s[i]);
  }
  template <class T>
  void write_single(const vector<T>& val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i) write_single(' ');
      write_single(val[i]);
    }
  }
};
Scanner Myifstream(stdin), Printer Myofstream(stdout);

Update on 7/21 2022

更新了快读快写的部分小细节

快读

// 快读第四版本
// 4. 
template<typename _Tp> inline void read(_Tp&x) {
  register int f = 1; register char ch = getchar();
  for (; ch < 48 || ch > 57; ch = getchar()) f = ch == '-' ? -1 : 1;
  for (; ch >= 48 || ch <= 57; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
  x *= f;
}
// 快写第二版本
// 2.
template<typename _Tp> inline void write(_Tp x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) write(x / 10);
  putchar(x % 10 ^ 48);
}

当然你也可以存到栈里面去,然后输出,因为递归是比较慢的。

2023~2023

其实还用了一份比较慢的板子,我也不知道为什么cin.streambuf()cout.streambuf()这么慢。
这个思路是最近在网上找到的,然后碾压很多其他的写法,5e6a+b只需要73ms,非常的快,吊打正常的fwrite(时间约为其 4 5 \frac{4}{5} 54左右)。
看过一点卡常的人应该都会知道mem...(比如memcpy/memset)这种函数比fillfor都要快(不吸氧气的时候比for快很多,吸了氧气比for快一点点),然后我们就可以利用这个性质,输出时每隔4个位置memcpy一下,这样就可以加速输出了。每四位的结果预处理一下即可。
都看到这儿了代码不用我贴了吧 (其实是因为代码太长放不下,不知道为什么csdn就炸了。。)
需要的可以去luogu上的快读快写板子(Elgo87的题目)的最优解去找我的代码,代码是公开的。如果你看不了我的代码,那你可以水过这道题(普通的快读快写应该是过不去的),然后再看我的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值