C++ 竞争性编程中的快速输入/输出

C++ 竞争性编程中的快速输入/输出,c++,posix,unistd.h,C++,Posix,Unistd.h,在竞争性编程竞赛的解决方案中,我多次遇到这段特殊的代码片段。我理解这段代码的基本用法,以克服时间限制,但我想更深入地理解它。我知道unistd.h允许访问系统调用包装函数,如fork、pipe和I/O原语(读、写等) 如果有人能向我解释或引导我找到有助于我进一步理解它的资源,那也将非常好 #include <stdlib.h> #include <stdint.h> #include <unistd.h> class FastInput { public:

在竞争性编程竞赛的解决方案中,我多次遇到这段特殊的代码片段。我理解这段代码的基本用法,以克服时间限制,但我想更深入地理解它。我知道unistd.h允许访问系统调用包装函数,如fork、pipe和I/O原语(读、写等)

如果有人能向我解释或引导我找到有助于我进一步理解它的资源,那也将非常好

#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
class FastInput {
public:
    FastInput() {
        m_dataOffset = 0;
        m_dataSize = 0;
        m_v = 0x80000000;
    }
    uint32_t ReadNext() {
        if (m_dataOffset == m_dataSize) {
            int r = read(0, m_buffer, sizeof(m_buffer));
            if (r <= 0) return m_v;
            m_dataOffset = 0;
            m_dataSize = 0;
            int i = 0;
            if (m_buffer[0] < '0') {
                if (m_v != 0x80000000) {
                    m_data[m_dataSize++] = m_v;
                    m_v = 0x80000000;
                }
                for (; (i < r) && (m_buffer[i] < '0'); ++i);
            }
            for (; i < r;) {
                if (m_buffer[i] >= '0') {
                    m_v = m_v * 10 + m_buffer[i] - 48;
                    ++i;
                } else {
                    m_data[m_dataSize++] = m_v;
                    m_v = 0x80000000;
                    for (i = i + 1; (i < r) && (m_buffer[i] < '0'); ++i);
                }
            }
        }
        return m_data[m_dataOffset++];
    }
public:
    uint8_t m_buffer[32768];
    uint32_t m_data[16384];
    size_t m_dataOffset, m_dataSize;
    uint32_t m_v;
};
class FastOutput {
public:
    FastOutput() {
        m_dataOffset = 0;
    }
    ~FastOutput() {
    }
    void Flush() {
        if (m_dataOffset) {
            if (write(1, m_data, m_dataOffset));
            m_dataOffset = 0;
        }
    }
    void PrintUint(uint32_t v, char d) {
        if (m_dataOffset + 11 > sizeof(m_data)) Flush();
        if (v < 100000) {
            if (v < 1000) {
                if (v < 10) {
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 1;
                } else if (v < 100) {
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 2;
                } else {
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 3;
                }
            } else {
                if (v < 10000) {
                    m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 4;
                } else {
                    m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 5;
                }
            }
        } else {
            if (v < 100000000) {
                if (v < 1000000) {
                    m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 6;
                } else if (v < 10000000) {
                    m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 7;
                } else {
                    m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 8;
                }
            } else {
                if (v < 1000000000) {
                    m_data[m_dataOffset + 8] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 9;
                } else {
                    m_data[m_dataOffset + 9] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 8] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
                    v /= 10;
                    m_data[m_dataOffset + 0] = v + 48;
                    m_dataOffset += 10;
                }
            }
        }
        m_data[m_dataOffset++] = d;
    }
    void PrintChar(char d) {
        if (m_dataOffset + 1 > sizeof(m_data)) Flush();
        m_data[m_dataOffset++] = d;
    }
    void ReplaceChar(int offset, char d) {
        m_data[m_dataOffset + offset] = d;
    }
public:
    uint8_t m_data[32768];
    size_t m_dataOffset;
};
#包括
#包括
#包括
类快速输入{
公众:
快速输入(){
m_dataOffset=0;
m_dataSize=0;
m_v=0x8000000;
}
uint32_t ReadNext(){
if(m_dataOffset==m_dataSize){
int r=read(0,m_缓冲区,sizeof(m_缓冲区));
如果(r='0'){
m_v=m_v*10+m_缓冲器[i]-48;
++一,;
}否则{
m_data[m_dataSize++]=m_v;
m_v=0x8000000;
对于(i=i+1;(isizeof(m_数据))Flush();
如果(v<100000){
如果(v<1000){
如果(v<10){
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=1;
}否则如果(v<100){
m_数据[m_数据偏移量+1]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=2;
}否则{
m_数据[m_数据偏移量+2]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+1]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=3;
}
}否则{
如果(v<10000){
m_数据[m_数据偏移量+3]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+2]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+1]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=4;
}否则{
m_数据[m_数据偏移量+4]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+3]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+2]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+1]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=5;
}
}
}否则{
如果(v<100000000){
如果(v<1000000){
m_数据[m_数据偏移量+5]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+4]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+3]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+2]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+1]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=6;
}否则如果(v<10000000){
m_数据[m_数据偏移量+6]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+5]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+4]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+3]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+2]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+1]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=7;
}否则{
m_数据[m_数据偏移量+7]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+6]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+5]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+4]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+3]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+2]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+1]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+0]=v+48;
m_dataOffset+=8;
}
}否则{
如果(v<100000000){
m_数据[m_数据偏移量+8]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+7]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+6]=v-v/10*10+48;
v/=10;
m_数据[m_数据偏移量+5]=v-v/10*10+
// I'm sure the compiler can figure out the inline part, but I'll add it anyways
template<unsigned int N> 
inline void print_uint_inner(uint32_t v) {
    m_data[m_dataOffset + N] = v - v / 10 * 10 + 48;
    print_uint_inner<N-1>(v / 10);
}

// For situations just like this, there's a trick to avoid having to define the base case separately.
inline void print_uint_inner<0>(uint32_t v) {
    m_data[m_dataOffset] = v - v / 10 * 10 + 48;
}

template<unsigned int N>
inline void print_uint_helper(uint32_t v) {
    print_uint_inner<N-1>(v);
    m_dataOffset += N;
}

// We could generate the compile-time binary search with templates too, rather than by hand.
void PrintUint(uint32_t v, char d) {
    if (m_dataOffset + 11 > sizeof(m_data)) Flush();
    if (v < 100000) {
        if (v < 1000) {
            if (v < 10) {
                print_uint_helper<1>(v);
            } else if (v < 100) {
                print_uint_helper<2>(v);
            } else {
                print_uint_helper<3>(v);
            }
        } else {
            if (v < 10000) {
                print_uint_helper<4>(v);
            } else {
                print_uint_helper<5>(v);
            }
        }
    } else {
        if (v < 100000000) {
            if (v < 1000000) {
                print_uint_helper<6>(v);
            } else if (v < 10000000) {
                print_uint_helper<7>(v);
            } else {
                print_uint_helper<8>(v);
            }
        } else {
            if (v < 1000000000) {
                print_uint_helper<9>(v);
            } else {
                print_uint_helper<10>(v);
            }
        }
    }
    m_data[m_dataOffset++] = d;
}