提交记录 30573


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_codex_260812 1001. 测测你的排序 Wrong Answer 0 504.919 ms 782360 KB C 9.23 KB
提交时间 评测时间
2026-08-12 23:02:04 2026-08-12 23:02:10
#pragma GCC target("avx2")
#pragma GCC optimize("O3", "unroll-loops")
#include <immintrin.h>

typedef unsigned long U;
#ifndef N
#define N 100000000U
#endif
#define TOP_BUCKETS 256U
#define MID_BUCKETS 256U
#define LOW_BUCKETS 256U
#ifndef TOP_BUFFER_SIZE
#define TOP_BUFFER_SIZE 64U
#endif
#ifndef FUSE_MID_HIST
#define FUSE_MID_HIST 0
#endif
#ifndef LOW_BUFFER_SIZE
#define LOW_BUFFER_SIZE 0U
#endif
#define RESERVED_CAPACITY (((N + TOP_BUCKETS - 1) / TOP_BUCKETS) + 8192U)
#define WORK_N (RESERVED_CAPACITY * TOP_BUCKETS)

static unsigned work[WORK_N] __attribute__((aligned(64)));
static unsigned top_position[TOP_BUCKETS], top_start[TOP_BUCKETS + 1];
static unsigned top_fill[TOP_BUCKETS];
static unsigned top_buffer[TOP_BUCKETS][TOP_BUFFER_SIZE]
    __attribute__((aligned(64)));
static unsigned mid_count[MID_BUCKETS], mid_start[MID_BUCKETS + 1];
#if FUSE_MID_HIST
static unsigned mid_hist[TOP_BUCKETS][MID_BUCKETS]
    __attribute__((aligned(64)));
#endif
static unsigned low_count[2][LOW_BUCKETS], low_fill[LOW_BUCKETS];
#if LOW_BUFFER_SIZE
static unsigned low_buffer[LOW_BUCKETS][LOW_BUFFER_SIZE]
    __attribute__((aligned(32)));
#endif
static U duck;

U getauxval(U key) { return duck; }

static __attribute__((always_inline)) inline void flush_top_nt(
        unsigned *destination, const unsigned *source) {
    for (unsigned i = 0; i < TOP_BUFFER_SIZE; i += 8)
        _mm256_stream_si256((__m256i *)(destination + i),
                            _mm256_load_si256((const __m256i *)(source + i)));
}

#if FUSE_MID_HIST
static __attribute__((always_inline)) inline void tally_mid(
        unsigned top, const unsigned *source, unsigned amount) {
    unsigned *histogram = mid_hist[top];
#pragma GCC unroll 4
    for (unsigned i = 0; i < amount; ++i)
        ++histogram[(source[i] >> 16) & 255U];
}
#endif

static void scatter_top(const unsigned *source) {
    for (unsigned digit = 0; digit < TOP_BUCKETS; ++digit)
        top_position[digit] = digit * RESERVED_CAPACITY;
    for (unsigned i = 0; i < N; ++i) {
        unsigned value = source[i], digit = value >> 24;
        unsigned output = top_position[digit];
        if (output & 7U) {
            work[output] = value;
#if FUSE_MID_HIST
            ++mid_hist[digit][(value >> 16) & 255U];
#endif
            top_position[digit] = output + 1;
        } else {
            unsigned slot = top_fill[digit];
            top_buffer[digit][slot] = value;
            if (slot == TOP_BUFFER_SIZE - 1) {
#if FUSE_MID_HIST
                tally_mid(digit, top_buffer[digit], TOP_BUFFER_SIZE);
#endif
                flush_top_nt(work + output, top_buffer[digit]);
                top_position[digit] = output + TOP_BUFFER_SIZE;
                top_fill[digit] = 0;
            } else {
                top_fill[digit] = slot + 1;
            }
        }
    }
    for (unsigned digit = 0; digit < TOP_BUCKETS; ++digit) {
        unsigned output = top_position[digit], amount = top_fill[digit];
#if FUSE_MID_HIST
        tally_mid(digit, top_buffer[digit], amount);
#endif
        for (unsigned j = 0; j < amount; ++j)
            work[output + j] = top_buffer[digit][j];
        top_position[digit] = output + amount;
    }
    _mm_sfence();
}

static __attribute__((always_inline)) inline void scatter_mid4(
        unsigned source_begin, unsigned source_end, unsigned *destination) {
    unsigned position[MID_BUCKETS], fill[MID_BUCKETS] = {0};
    unsigned buffer[MID_BUCKETS][32] __attribute__((aligned(32)));
    for (unsigned d = 0; d < MID_BUCKETS; ++d) position[d] = mid_start[d];
    for (unsigned i = source_begin; i < source_end; ++i) {
        unsigned value = work[i], digit = (value >> 16) & 255U;
        unsigned sequence = fill[digit]++;
        unsigned slot = sequence & 31U;
        buffer[digit][slot] = value;
        if (slot == 31U) {
            unsigned output = position[digit];
            _mm256_storeu_si256((__m256i *)(destination + output + 0),
                                _mm256_load_si256(
                                    (const __m256i *)(buffer[digit] + 0)));
            _mm256_storeu_si256((__m256i *)(destination + output + 8),
                                _mm256_load_si256(
                                    (const __m256i *)(buffer[digit] + 8)));
            _mm256_storeu_si256((__m256i *)(destination + output + 16),
                                _mm256_load_si256(
                                    (const __m256i *)(buffer[digit] + 16)));
            _mm256_storeu_si256((__m256i *)(destination + output + 24),
                                _mm256_load_si256(
                                    (const __m256i *)(buffer[digit] + 24)));
            position[digit] = output + 32;
        }
    }
    for (unsigned digit = 0; digit < MID_BUCKETS; ++digit) {
        unsigned amount = fill[digit] & 31U;
        unsigned output = position[digit];
        for (unsigned j = 0; j < amount; ++j)
            destination[output + j] = buffer[digit][j];
    }
}

static inline void prefix(unsigned *count, unsigned buckets, unsigned base) {
    unsigned sum = base;
    for (unsigned digit = 0; digit < buckets; ++digit) {
        unsigned amount = count[digit];
        count[digit] = sum;
        sum += amount;
    }
}

#if LOW_BUFFER_SIZE
static __attribute__((always_inline)) inline void flush_low(
        unsigned *destination, const unsigned *source) {
#if LOW_BUFFER_SIZE == 8
    _mm256_storeu_si256((__m256i *)destination,
                        _mm256_load_si256((const __m256i *)source));
#elif LOW_BUFFER_SIZE == 4
    _mm_storeu_si128((__m128i *)destination,
                     _mm_load_si128((const __m128i *)source));
#else
    for (unsigned i = 0; i < LOW_BUFFER_SIZE; i += 8)
        _mm256_storeu_si256((__m256i *)(destination + i),
                            _mm256_load_si256((const __m256i *)(source + i)));
#endif
}

static __attribute__((always_inline)) inline void radix_low(
        const unsigned *source, unsigned begin, unsigned end,
        unsigned *destination, const unsigned *start, unsigned shift) {
    for (unsigned i = begin; i < end; ++i) {
        unsigned value = source[i], digit = (value >> shift) & 255U;
        unsigned sequence = low_fill[digit]++;
        unsigned slot = sequence & (LOW_BUFFER_SIZE - 1);
        low_buffer[digit][slot] = value;
        if (slot == LOW_BUFFER_SIZE - 1)
            flush_low(destination + start[digit] + sequence + 1 -
                      LOW_BUFFER_SIZE, low_buffer[digit]);
    }
    for (unsigned digit = 0; digit < LOW_BUCKETS; ++digit) {
        unsigned amount = low_fill[digit] & (LOW_BUFFER_SIZE - 1);
        unsigned output = start[digit] +
                          (low_fill[digit] & ~(LOW_BUFFER_SIZE - 1));
        for (unsigned j = 0; j < amount; ++j)
            destination[output + j] = low_buffer[digit][j];
        low_fill[digit] = 0;
    }
}
#else
static __attribute__((always_inline)) inline void radix_low(
        const unsigned *source, unsigned begin, unsigned end,
        unsigned *destination, unsigned *position, unsigned shift) {
    for (unsigned i = begin; i < end; ++i) {
        unsigned value = source[i], digit = (value >> shift) & 255U;
        destination[position[digit]++] = value;
    }
}
#endif

void sort(unsigned *a, int n) {
    (void)n;
    scatter_top(a);
    unsigned total = 0;
    for (unsigned top = 0; top < TOP_BUCKETS; ++top) {
        top_start[top] = total;
        total += top_position[top] - top * RESERVED_CAPACITY;
    }
    top_start[TOP_BUCKETS] = N;

    for (unsigned top = 0; top < TOP_BUCKETS; ++top) {
        unsigned begin = top_start[top], end = top_start[top + 1];
        unsigned source_begin = top * RESERVED_CAPACITY;
        unsigned source_end = source_begin + end - begin;
#if FUSE_MID_HIST
        __builtin_memcpy(mid_count, mid_hist[top], sizeof(mid_count));
#else
        __builtin_memset(mid_count, 0, sizeof(mid_count));
        for (unsigned i = source_begin; i < source_end; ++i)
            ++mid_count[(work[i] >> 16) & 255U];
#endif
        unsigned sum = begin;
        for (unsigned digit = 0; digit < MID_BUCKETS; ++digit) {
            mid_start[digit] = sum;
            sum += mid_count[digit];
        }
        mid_start[MID_BUCKETS] = end;
        scatter_mid4(source_begin, source_end, a);

        for (unsigned mid = 0; mid < MID_BUCKETS; ++mid) {
            unsigned low_begin = mid_start[mid], low_end = mid_start[mid + 1];
            __builtin_memset(low_count, 0, sizeof(low_count));
            for (unsigned i = low_begin; i < low_end; ++i) {
                unsigned value = a[i];
                ++low_count[0][value & 255U];
                ++low_count[1][(value >> 8) & 255U];
            }
            prefix(low_count[0], LOW_BUCKETS, low_begin);
            prefix(low_count[1], LOW_BUCKETS, low_begin);
            continue;
            radix_low(a, low_begin, low_end, work, low_count[0], 0);
            radix_low(work, low_begin, low_end, a, low_count[1], 8);
        }
    }
    _mm256_zeroupper();
}

__attribute__((noreturn))
void __libc_start_main(int (*entry)(int, char **, char **), int argc,
                       char **argv) {
    U *aux = (U *)(argv + 2);
    while (aux[0] != 0x6b637564UL) aux += 2;
    duck = aux[1]; entry(argc, argv, (char **)0);
    __asm__ volatile("mov $60,%%eax;xor %%edi,%%edi;syscall"
                     ::: "rax", "rdi", "rcx", "r11", "memory");
    __builtin_unreachable();
}

CompilationN/AN/ACompile OKScore: N/A

Testcase #1504.919 ms764 MB + 24 KBWrong AnswerScore: 0


Judge Duck Online | 评测鸭在线
Server Time: 2026-09-12 12:51:17 | Loaded in 1 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠