这种奇怪的I/O方法是如何工作的? 在C++中输入输入时,我只使用了SnfF/PrimTf和CIN/CUT。现在我最近遇到了以一种奇怪的方式进行I/O的代码
还请注意,此I/O方法导致代码运行速度极快,因为此代码使用与大多数其他代码几乎相同的算法,但执行时间要短得多。为什么I/O速度如此之快?一般来说,它是如何工作的 编辑:代码这种奇怪的I/O方法是如何工作的? 在C++中输入输入时,我只使用了SnfF/PrimTf和CIN/CUT。现在我最近遇到了以一种奇怪的方式进行I/O的代码,c++,io,C++,Io,还请注意,此I/O方法导致代码运行速度极快,因为此代码使用与大多数其他代码几乎相同的算法,但执行时间要短得多。为什么I/O速度如此之快?一般来说,它是如何工作的 编辑:代码 #include <bits/stdtr1c++.h> #define MAXN 200010 #define MAXQ 200010 #define MAXV 1000010 #define clr(ar) memset(ar, 0, sizeof(ar)) #define read() freo
#include <bits/stdtr1c++.h>
#define MAXN 200010
#define MAXQ 200010
#define MAXV 1000010
#define clr(ar) memset(ar, 0, sizeof(ar))
#define read() freopen("lol.txt", "r", stdin)
using namespace std;
const int block_size = 633;
long long res, out[MAXQ]; int n, q, ar[MAXN], val[MAXN], freq[MAXV];
namespace fastio{
int ptr, ye;
char temp[25], str[8333667], out[8333669];
void init(){
ptr = 0, ye = 0;
fread(str, 1, 8333667, stdin);
}
inline int number(){
int i, j, val = 0;
while (str[ptr] < 45 || str[ptr] > 57) ptr++;
while (str[ptr] > 47 && str[ptr] < 58) val = (val * 10) + (str[ptr++] - 48);
return val;
}
inline void convert(long long x){
int i, d = 0;
for (; ;){
temp[++d] = (x % 10) + 48;
x /= 10;
if (!x) break;
}
for (i = d; i; i--) out[ye++] = temp[i];
out[ye++] = 10;
}
inline void print(){
fwrite(out, 1, ye, stdout);
} }
struct query{
int l, r, d, i;
inline query() {}
inline query(int a, int b, int c){
i = c;
l = a, r = b, d = l / block_size;
}
inline bool operator < (const query& other) const{
if (d != other.d) return (d < other.d);
return ((d & 1) ? (r < other.r) : (r > other.r));
} } Q[MAXQ];
void compress(int n, int* in, int* out){
unordered_map <int, int> mp;
for (int i = 0; i < n; i++) out[i] = mp.emplace(in[i], mp.size()).first->second; }
inline void insert(int i){
res += (long long)val[i] * (1 + 2 * freq[ar[i]]++); }
inline void erase(int i){
res -= (long long)val[i] * (1 + 2 * --freq[ar[i]]); }
inline void run(){
sort(Q, Q + q);
int i, l, r, a = 0, b = 0;
for (res = 0, i = 0; i < q; i++){
l = Q[i].l, r = Q[i].r;
while (a > l) insert(--a);
while (b <= r) insert(b++);
while (a < l) erase(a++);
while (b > (r + 1)) erase(--b);
out[Q[i].i] = res;
}
for (i = 0; i < q; i++) fastio::convert(out[i]); }
int main(){
fastio::init();
int n, i, j, k, a, b;
n = fastio::number();
q = fastio::number();
for (i = 0; i < n; i++) val[i] = fastio::number();
compress(n, val, ar);
for (i = 0; i < q; i++){
a = fastio::number();
b = fastio::number();
Q[i] = query(a - 1, b - 1, i);
}
run();
fastio::print();
return 0; }
#包括
#定义MAXN 200010
#定义MAXQ 200010
#定义MAXV 1000010
#定义clr(ar)memset(ar,0,sizeof(ar))
#定义read()freopen(“lol.txt”,“r”,stdin)
使用名称空间std;
const int block_size=633;
long-long-res,out[MAXQ];int n,q,ar[MAXN],val[MAXN],freq[MAXV];
命名空间禁食{
int ptr,叶;
字符温度[25],str[8333667],out[8333669];
void init(){
ptr=0,ye=0;
fread(str,18333667,stdin);
}
内联整数(){
int i,j,val=0;
而(str[ptr]<45 | | str[ptr]>57)ptr++;
而(str[ptr]>47&&str[ptr]<58)val=(val*10)+(str[ptr++]-48);
返回val;
}
内联void转换(长x){
int i,d=0;
对于(;;){
温度[++d]=(x%10)+48;
x/=10;
如果(!x)中断;
}
对于(i=d;i;i--)out[ye++]=temp[i];
out[ye++]=10;
}
内联无效打印(){
写(out,1,ye,stdout);
} }
结构查询{
int l,r,d,i;
内联查询(){}
内联查询(inta、intb、intc){
i=c;
l=a,r=b,d=l/块尺寸;
}
内联布尔运算符<(常量查询和其他)常量{
如果(d!=other.d)返回(dother.r));
}}Q[MAXQ];
无效压缩(int n,int*in,int*out){
无序地图mp;
对于(inti=0;isecond;}
内联无效插入(int i){
res+=(long-long)val[i]*(1+2*freq[ar[i]]++;}
内联无效擦除(int i){
res-=(long-long)val[i]*(1+2*--freq[ar[i]];}
内联无效运行(){
排序(Q,Q+Q);
int i,l,r,a=0,b=0;
对于(res=0,i=0;il)插入(--a);
而(b(r+1))擦除(--b);
out[Q[i]=res;
}
对于(i=0;i
此解决方案(624毫秒,32 MB RAM使用)使用单个fread和从内存手动解析数字(因此它使用更多内存);许多其他解决方案都比较慢,使用<代码> SCANF< <代码>(1620毫秒9MB)或C++ IOSWATE <代码> CIN < /代码>(3118毫秒,15毫巴)。并非所有解决方案的差异都来自输入-输出和解析(解决方案方法也有差异),但有些是
fread(str, 1, 8333667, stdin);
此代码使用singlefread
libcall读取高达8MB的文件,这是一个完整的文件。该文件最多可以有2(n,t)+200000(a_i)+2*200000(l,r)个6/7位数字,有或没有换行符,或用一个(?)空格分隔,因此数字最多约8个字符(数字最多6或7个字符,因为1000000也是允许的,1个空格或\n
);最大输入文件大小约为0.6 M*8字节=~5 MB
inline int number(){
int i, j, val = 0;
while (str[ptr] < 45 || str[ptr] > 57) ptr++;
while (str[ptr] > 47 && str[ptr] < 58) val = (val * 10) + (str[ptr++] - 48);
return val;
}
实际读取使用此
fastio::number()
方法;其他解决方案使用调用scanf
或iostream操作符,请使问题自我维持。也就是说,它不应该依赖于本网站以外的内容。在问题中张贴相关代码。你是在问为什么这个char str[8333667];fread(str,18333667,stdin)代码>可以比其他方法更快吗?请将该代码的相关部分添加到您的问题中。请使用此代码使用任务特定的解析,它比SCANF或C++ IoStudio CIN快,因为该代码只解析许多可能的数字格式的小子集,不检查输入错误。这段代码中的逻辑更少,分支更少,所以速度更快。只有1个系统调用可以使用fread将完整文件一次读取到内存中,没有太多的系统调用和小的4KB或类似于经典scanf/cin的缓冲区。@akka检查错误吗?比如如果文件无法打开会发生什么?或者读取文件时出错?或者如果解析内容时出错?这些(以及更多)情况需要检查和处理。我想知道通过setbuf(stdin,NULL)禁用stdin
上的缓冲是否会提高性能代码>或简单地调用read(STDIN_FILENO,str,8333667)代码>而不是fread(…)代码>。这可能需要几毫秒的时间。使用scanf/cin禁用缓冲将使事情变得更慢(更多的系统调用),并且永远不应该使用这个“fastio”;以任何形式,read和fread,带或不带setbuf。这只是不正确、不安全、不必要/不需要的过早优化。“我们应该忘记小效率,比如说97%的时间:过早优化是万恶之源。然而,我们不应该放弃我们的机会,因为关键的3%“”使用scanf/cin禁用缓冲将使事情变得更慢(更多的系统调用),这将取决于底层实现——它很可能导致更少的系统调用。这种“fastio”在一般情况下是不应该被使用的,但是对于代码IO性能竞赛,胜利者几乎可以保证必须做类似的事情;此任务将接受任何I/O样式,并且w
n = fastio::number();
q = fastio::number();
for (i = 0; i < n; i++) val[i] = fastio::number();
for (i = 0; i < q; i++){
a = fastio::number();
b = fastio::number();
for (int i = 0; i < N; i++) {
scanf("%d", &(arr[i]));
add(arr[i]);
}
for (int i = 1; i <= n; ++i)
cin >> a[i];