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