提交记录 30590


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_codex_260812 1001. 测测你的排序 Accepted 100 656.154 ms 782400 KB C 10.92 KB
提交时间 评测时间
2026-08-12 23:15:15 2026-08-12 23:15:20
#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
#ifndef MID_BITS
#define MID_BITS 8U
#endif
#define MID_BUCKETS (1U << MID_BITS)
#define LOW_BITS (24U - MID_BITS)
#ifndef LOW0_BITS
#define LOW0_BITS ((LOW_BITS + 1U) / 2U)
#endif
#define LOW1_BITS (LOW_BITS - LOW0_BITS)
#define LOW0_BUCKETS (1U << LOW0_BITS)
#define LOW1_BUCKETS (1U << LOW1_BITS)
#define LOW_BUCKETS (LOW0_BUCKETS > LOW1_BUCKETS ? \
                     LOW0_BUCKETS : LOW1_BUCKETS)
#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
#ifndef RESERVE_BITS
#define RESERVE_BITS 6U
#endif
#ifndef RESERVE_CAPACITY
#define RESERVE_CAPACITY 128U
#endif
#define RESERVE_BUCKETS (1U << RESERVE_BITS)
#define RESERVE_HIGH_BITS (LOW_BITS - RESERVE_BITS)
#define RESERVE_HIGH_BUCKETS (1U << RESERVE_HIGH_BITS)
#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];
static unsigned reserve_count[RESERVE_HIGH_BUCKETS];
static unsigned short reserve_fill[RESERVE_BUCKETS];
static unsigned short reserve_work[RESERVE_BUCKETS * RESERVE_CAPACITY]
    __attribute__((aligned(64)));
#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] >> LOW_BITS) & (MID_BUCKETS - 1U)];
}
#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 >> LOW_BITS) & (MID_BUCKETS - 1U)];
#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];
        unsigned digit = (value >> LOW_BITS) & (MID_BUCKETS - 1U);
        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,
        unsigned mask, unsigned buckets) {
    for (unsigned i = begin; i < end; ++i) {
        unsigned value = source[i], digit = (value >> shift) & mask;
        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 < 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,
        unsigned mask, unsigned buckets) {
    (void)buckets;
    for (unsigned i = begin; i < end; ++i) {
        unsigned value = source[i], digit = (value >> shift) & mask;
        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] >> LOW_BITS) & (MID_BUCKETS - 1U)];
#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(reserve_count, 0, sizeof(reserve_count));
            __builtin_memset(reserve_fill, 0, sizeof(reserve_fill));
            for (unsigned i = low_begin; i < low_end; ++i) {
                unsigned value = (unsigned short)a[i];
                unsigned low = value & (RESERVE_BUCKETS - 1U);
                reserve_work[low * RESERVE_CAPACITY + reserve_fill[low]++] =
                    (unsigned short)value;
                ++reserve_count[(value >> RESERVE_BITS) &
                                (RESERVE_HIGH_BUCKETS - 1U)];
            }
            prefix(reserve_count, RESERVE_HIGH_BUCKETS, low_begin);
            unsigned fixed = (top << 24) | (mid << LOW_BITS);
            for (unsigned low = 0; low < RESERVE_BUCKETS; ++low) {
                const unsigned short *source =
                    reserve_work + low * RESERVE_CAPACITY;
                unsigned amount = reserve_fill[low];
                for (unsigned i = 0; i < amount; ++i) {
                    unsigned value = source[i];
                    unsigned high = (value >> RESERVE_BITS) &
                                    (RESERVE_HIGH_BUCKETS - 1U);
                    a[reserve_count[high]++] = fixed | value;
                }
            }
        }
    }
    _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 #1656.154 ms764 MB + 64 KBAcceptedScore: 100


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