提交记录 40195


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_dsh_260814 wc2017b1. 【WC2017】挑战-任务1 Accepted 100 1.927 s 1564284 KB C 7.51 KB
提交时间 评测时间
2026-08-17 21:31:24 2026-08-17 21:31:33
// wc2017b1 v12: u16 sidecar in the lower passes (halve L3/L2 data width).
// sort_bucket scatters low-16 bits (u16) into scratch; sort16 sorts u16 keys;
// final reconstruct ORs the sub-bucket top16 and NT-flushes to a[].
#include <immintrin.h>
#include <string.h>
#include <emmintrin.h>
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;

__attribute__((target("avx2")))
static inline void flush_nt(u32 *dst, const u32 *src) {
    __m256i v0 = _mm256_loadu_si256((const __m256i*)(src + 0));
    __m256i v1 = _mm256_loadu_si256((const __m256i*)(src + 8));
    __m256i v2 = _mm256_loadu_si256((const __m256i*)(src + 16));
    __m256i v3 = _mm256_loadu_si256((const __m256i*)(src + 24));
    __m256i v4 = _mm256_loadu_si256((const __m256i*)(src + 32));
    __m256i v5 = _mm256_loadu_si256((const __m256i*)(src + 40));
    __m256i v6 = _mm256_loadu_si256((const __m256i*)(src + 48));
    __m256i v7 = _mm256_loadu_si256((const __m256i*)(src + 56));
    __m256i v8 = _mm256_loadu_si256((const __m256i*)(src + 64));
    __m256i v9 = _mm256_loadu_si256((const __m256i*)(src + 72));
    __m256i v10 = _mm256_loadu_si256((const __m256i*)(src + 80));
    __m256i v11 = _mm256_loadu_si256((const __m256i*)(src + 88));
    __m256i v12 = _mm256_loadu_si256((const __m256i*)(src + 96));
    __m256i v13 = _mm256_loadu_si256((const __m256i*)(src + 104));
    __m256i v14 = _mm256_loadu_si256((const __m256i*)(src + 112));
    __m256i v15 = _mm256_loadu_si256((const __m256i*)(src + 120));
    _mm256_stream_si256((__m256i*)(dst + 0), v0);
    _mm256_stream_si256((__m256i*)(dst + 8), v1);
    _mm256_stream_si256((__m256i*)(dst + 16), v2);
    _mm256_stream_si256((__m256i*)(dst + 24), v3);
    _mm256_stream_si256((__m256i*)(dst + 32), v4);
    _mm256_stream_si256((__m256i*)(dst + 40), v5);
    _mm256_stream_si256((__m256i*)(dst + 48), v6);
    _mm256_stream_si256((__m256i*)(dst + 56), v7);
    _mm256_stream_si256((__m256i*)(dst + 64), v8);
    _mm256_stream_si256((__m256i*)(dst + 72), v9);
    _mm256_stream_si256((__m256i*)(dst + 80), v10);
    _mm256_stream_si256((__m256i*)(dst + 88), v11);
    _mm256_stream_si256((__m256i*)(dst + 96), v12);
    _mm256_stream_si256((__m256i*)(dst + 104), v13);
    _mm256_stream_si256((__m256i*)(dst + 112), v14);
    _mm256_stream_si256((__m256i*)(dst + 120), v15);
}

#define NB 256
#define LINE 128

static u32 tmp[200000000 + NB * LINE] __attribute__((aligned(64)));
static u32 staging[NB * LINE] __attribute__((aligned(64)));
static u32 cnt[NB];
static u32 rbase[NB];
static u32 pbase[NB];
static u32 off[NB];
static u8  pos[NB];
static u16 scratch[1048576] __attribute__((aligned(64)));
static u16 scratch2[65536] __attribute__((aligned(64)));
static u16 scratch3[65536] __attribute__((aligned(64)));
static u32 bc[256];
static u32 bc2[256];
static u32 sstart[256];
static u32 spos[256];
static u32 scount[256];

static void scatter_top(u32 *src, u32 *dst, int n) {
    int i, j;
    for (j = 0; j < NB; j++) cnt[j] = 0;
    int n8 = n & ~3;
    for (i = 0; i < n8; i += 4) {
        cnt[src[i+0]>>24]++;
        cnt[src[i+1]>>24]++;
        cnt[src[i+2]>>24]++;
        cnt[src[i+3]>>24]++;
    }
    for (; i < n; i++) cnt[src[i] >> 24]++;
    { u32 t = 0, p = 0; for (j = 0; j < NB; j++) { u32 c = cnt[j]; rbase[j] = t; pbase[j] = p; t += c; p = (p + c + 127) & ~127u; } }
    for (j = 0; j < NB; j++) { off[j] = pbase[j]; pos[j] = 0; }
#define S1(X) do { u32 x_ = (X); u32 b_ = x_ >> 24; u32 p_ = pos[b_]; \
    staging[b_ * LINE + p_] = x_; p_++; \
    if (p_ == LINE) { u32 go_ = off[b_]; flush_nt(dst + go_, staging + b_ * LINE); off[b_] = go_ + LINE; p_ = 0; } \
    pos[b_] = (u8)p_; } while (0)
    int n8s = n & ~3;
    for (i = 0; i < n8s; i += 4) {
        S1(src[i+0]);
        S1(src[i+1]);
        S1(src[i+2]);
        S1(src[i+3]);
    }
    for (; i < n; i++) S1(src[i]);
#undef S1
    for (j = 0; j < NB; j++) { u32 p = pos[j]; if (p > 0) __builtin_memcpy(dst + off[j], staging + j * LINE, p * 4); }
}

__attribute__((target("avx2")))
static inline void flush_range_nt(u32 *dst, const u16 *src, int m, u32 top16) {
    int mi = 0;
    // scalar tail until 32-byte aligned destination
    while ((((unsigned long)(dst + mi)) & 31) && mi < m) { dst[mi] = ((u32)src[mi]) | top16; mi++; }
    // AVX2 path: load u16, expand to u32, OR top16, NT store.
    // 8 u16 -> 8 u32 per 32-byte dst. Use 16 u16 -> 16 u32 (two 32B stores).
    for (; mi + 16 <= m; mi += 16) {
        __m128i lo = _mm_loadu_si128((const __m128i*)(src + mi));
        __m256i a0 = _mm256_cvtepu16_epi32(lo);
        __m256i t = _mm256_set1_epi32((int)top16);
        __m256i o0 = _mm256_or_si256(a0, t);
        _mm256_stream_si256((__m256i*)(dst + mi + 0), o0);
        // second half (next 8 u16 -> 8 u32)
        __m128i hi = _mm_loadu_si128((const __m128i*)(src + mi + 8));
        __m256i a1 = _mm256_cvtepu16_epi32(hi);
        __m256i o1 = _mm256_or_si256(a1, t);
        _mm256_stream_si256((__m256i*)(dst + mi + 8), o1);
    }
    for (; mi < m; mi++) dst[mi] = ((u32)src[mi]) | top16;
}

static void sort16(u16 *src, u32 *dst, int m, u32 top16) {
    int i, j;
    for (j = 0; j < 256; j++) bc[j] = 0;
    int m8 = m & ~3;
    for (i = 0; i < m8; i += 4) {
        bc[src[i+0]&255]++;
        bc[src[i+1]&255]++;
        bc[src[i+2]&255]++;
        bc[src[i+3]&255]++;
    }
    for (; i < m; i++) bc[src[i] & 255]++;
    for (j = 1; j < 256; j++) bc[j] += bc[j-1];
    for (j = 0; j < 256; j++) bc2[j] = 0;
    int rm = m & ~3;
    for (i = m - 1; i >= rm; i--) { u16 x = src[i]; scratch2[--bc[x & 255]] = x; bc2[(x >> 8) & 255]++; }
    for (i = rm - 1; i >= 0; i -= 4) {
        u16 x0=src[i-0]; scratch2[--bc[x0&255]]=x0; bc2[(x0>>8)&255]++;
        u16 x1=src[i-1]; scratch2[--bc[x1&255]]=x1; bc2[(x1>>8)&255]++;
        u16 x2=src[i-2]; scratch2[--bc[x2&255]]=x2; bc2[(x2>>8)&255]++;
        u16 x3=src[i-3]; scratch2[--bc[x3&255]]=x3; bc2[(x3>>8)&255]++;
    }
    for (j = 1; j < 256; j++) bc2[j] += bc2[j-1];
    for (i = m - 1; i >= rm; i--) { u16 x = scratch2[i]; scratch3[--bc2[(x >> 8) & 255]] = x; }
    for (i = rm - 1; i >= 0; i -= 4) {
        u16 x0=scratch2[i-0]; scratch3[--bc2[(x0>>8)&255]]=x0;
        u16 x1=scratch2[i-1]; scratch3[--bc2[(x1>>8)&255]]=x1;
        u16 x2=scratch2[i-2]; scratch3[--bc2[(x2>>8)&255]]=x2;
        u16 x3=scratch2[i-3]; scratch3[--bc2[(x3>>8)&255]]=x3;
    }
    flush_range_nt(dst, scratch3, m, top16);
}

static void sort_bucket(u32 *src, u32 *dst, int m, int bj) {
    int i, j;
    for (j = 0; j < 256; j++) bc[j] = 0;
    int mb8 = m & ~3;
    for (i = 0; i < mb8; i += 4) {
        bc[(src[i+0]>>16)&255]++;
        bc[(src[i+1]>>16)&255]++;
        bc[(src[i+2]>>16)&255]++;
        bc[(src[i+3]>>16)&255]++;
    }
    for (; i < m; i++) bc[(src[i] >> 16) & 255]++;
    { u32 t = 0; for (j = 0; j < 256; j++) { u32 c = bc[j]; scount[j] = c; sstart[j] = t; spos[j] = t; t += c; } }
    for (i = 0; i < mb8; i += 4) {
        u32 x0=src[i+0],b0=(x0>>16)&255; scratch[spos[b0]++]=(u16)x0;
        u32 x1=src[i+1],b1=(x1>>16)&255; scratch[spos[b1]++]=(u16)x1;
        u32 x2=src[i+2],b2=(x2>>16)&255; scratch[spos[b2]++]=(u16)x2;
        u32 x3=src[i+3],b3=(x3>>16)&255; scratch[spos[b3]++]=(u16)x3;
    }
    for (; i < m; i++) { u32 x = src[i]; u32 b = (x >> 16) & 255; scratch[spos[b]++] = (u16)x; }
    for (j = 0; j < 256; j++) { int c = scount[j]; if (c > 0) sort16(scratch + sstart[j], dst + sstart[j], c, ((u32)((bj<<8)|j))<<16); }
}

void sort(unsigned *aa, int n) {
    u32 *a = (u32*)aa;
    int j;
    scatter_top(a, tmp, n);
    for (j = 0; j < NB; j++) {
        int m = (int)cnt[j];
        if (m > 0) sort_bucket(tmp + pbase[j], a + rbase[j], m, j);
    }
}

CompilationN/AN/ACompile OKScore: N/A

Testcase #147.1 ms1 MB + 8 KBAcceptedScore: 34

Testcase #21.008 s763 MB + 952 KBAcceptedScore: 33

Testcase #31.927 s1527 MB + 636 KBAcceptedScore: 33


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