提交记录 67743


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_dsh_v41_0919 wc2017b1. 【WC2017】挑战-任务1 Accepted 100 1.973 s 1369896 KB C++17 6.80 KB
提交时间 评测时间
2026-09-20 00:02:48 2026-09-20 05:47:52
/* wc2017b1 pack3: same as fs2 (fixed-stride MSD by the top byte, no counting
 * pass) but the staging buffer stores only the low 24 bits of every element
 * (3 bytes each, unaligned 4-byte stores, 1 padding byte per bucket), which
 * cuts the first-touch page-fault cost and the scatter traffic by 25%.
 * The bucket phase then sub-buckets by byte 2 (fixed stride) and LSD-sorts
 * bytes 0,1 inside each ~m/256-element sub-bucket straight into `a`. */
#include <stdlib.h>
#include <string.h>
#include <immintrin.h>
#pragma GCC target("avx2")

/* non-temporal copy: the destination region is written completely, so the
   RFO read that a regular store would need is pure waste. */
static void nt_copy(unsigned *d, const unsigned *s, unsigned cnt) {
    unsigned i = 0;
    while (i < cnt && (((unsigned long)(d + i)) & 31u)) { d[i] = s[i]; i++; }
    for (; i + 8 <= cnt; i += 8)
        _mm256_stream_si256((__m256i *)(d + i), _mm256_loadu_si256((const __m256i *)(s + i)));
    for (; i < cnt; i++) d[i] = s[i];
}

static unsigned g_c0[256], g_c1[256], g_c2[256];

static void bucket_phase(unsigned *a, const unsigned char *tp, int m, unsigned short *scr,
                         unsigned *ap, unsigned short *loc, unsigned *st, unsigned stride2, unsigned topb) {
    (void)a;
    static unsigned fill2[256];
    unsigned off2[256];
    memset(fill2, 0, sizeof(fill2));
    int of = 0;
    {
        const unsigned char *q = tp;
        for (int i = 0; i < m; i++) {
            unsigned v = *(const unsigned *)q & 0xFFFFFFu;
            q += 3;
            unsigned k = (v >> 16) & 255u;
            unsigned f = fill2[k];
            if (f >= stride2) { of = 1; break; }
            scr[(size_t)k * stride2 + f] = (unsigned short)v;
            fill2[k] = f + 1;
        }
    }
    if (of) {                              /* adversarial: exact counting partition */
        memset(g_c1, 0, sizeof(g_c1));
        const unsigned char *q = tp;
        for (int i = 0; i < m; i++) { g_c1[(*(const unsigned *)q >> 16) & 255u]++; q += 3; }
        unsigned t = 0;
        for (int k = 0; k < 256; k++) { unsigned c = g_c1[k]; g_c1[k] = t; off2[k] = t; t += c; fill2[k] = c; }
        q = tp;
        for (int i = 0; i < m; i++) { unsigned v = *(const unsigned *)q & 0xFFFFFFu; q += 3; scr[g_c1[(v >> 16) & 255u]++] = (unsigned short)v; }
    } else {
        unsigned t = 0;
        for (int k = 0; k < 256; k++) { off2[k] = t; t += fill2[k]; }
    }
    for (int k = 0; k < 256; k++) {
        unsigned cnt = fill2[k];
        unsigned short *sk = scr + (of ? (size_t)off2[k] : (size_t)k * stride2);
        unsigned topk = topb | ((unsigned)k << 16);
        if (cnt == 0) continue;
        if (cnt == 1) { ap[off2[k]] = (unsigned)sk[0] | topk; continue; }
        memset(g_c1, 0, sizeof(g_c1));
        for (unsigned i = 0; i < cnt; i++) g_c1[sk[i] & 255u]++;
        unsigned t2 = 0;
        for (int q = 0; q < 256; q++) { unsigned c = g_c1[q]; g_c1[q] = t2; t2 += c; }
        memset(g_c2, 0, sizeof(g_c2));
        for (unsigned i = 0; i < cnt; i++) {
            unsigned v = sk[i];
            loc[g_c1[v & 255u]++] = (unsigned short)v;
            g_c2[(v >> 8) & 255u]++;
        }
        t2 = 0;
        for (int q = 0; q < 256; q++) { unsigned c = g_c2[q]; g_c2[q] = t2; t2 += c; }
        for (unsigned i = 0; i < cnt; i++) { unsigned v = loc[i]; st[g_c2[(v >> 8) & 255u]++] = v | topk; }
        nt_copy(ap + off2[k], st, cnt);
    }
}

void sort(unsigned *a, int n) {
    if (n <= 1) return;
    unsigned stride = (unsigned)((n + 255) / 256) + (unsigned)(n >> 9) + 4096;
    size_t stride3 = (size_t)stride * 3u + 8u;          /* bytes per bucket + pad */
    unsigned char *tmp = (unsigned char *)malloc(stride3 * 256u);
    if (!tmp) return;
    static unsigned fill[256];
    memset(fill, 0, sizeof(fill));
    int i = 0, of = 0;
    for (; i < n; i++) {
        unsigned v = a[i];
        unsigned b = v >> 24;
        unsigned f = fill[b];
        if (f >= stride) { of = 1; break; }
        *(unsigned *)(tmp + (size_t)b * stride3 + (size_t)f * 3u) = v & 0xFFFFFFu;
        fill[b] = f + 1;
    }
    if (of) {
        free(tmp);
        /* adversarial distribution: exact counting partition into a packed buffer */
        memset(g_c0, 0, sizeof(g_c0));
        for (int k = 0; k < n; k++) g_c0[a[k] >> 24]++;
        size_t offb[257];
        unsigned offw[257];
        size_t s = 0; unsigned w = 0; unsigned maxb = 0;
        for (int k = 0; k < 256; k++) { offb[k] = s; offw[k] = w; unsigned c = g_c0[k]; s += (size_t)c * 3u + 1u; w += c; if (c > maxb) maxb = c; }
        offb[256] = s; offw[256] = w;
        unsigned char *tmp2 = (unsigned char *)malloc(s + 8);
        if (!tmp2) return;
        {
            size_t pos[256];
            for (int k = 0; k < 256; k++) pos[k] = offb[k];
            for (int k = 0; k < n; k++) {
                unsigned v = a[k];
                *(unsigned *)(tmp2 + pos[v >> 24]) = v & 0xFFFFFFu;
                pos[v >> 24] += 3;
            }
        }
        unsigned stride2b = (maxb + 255) / 256 + (maxb >> 9) + 1024;
        unsigned short *scr = (unsigned short *)malloc(((size_t)stride2b * 256u + 1024u) * 2u);
        unsigned short *locs2 = (unsigned short *)malloc((size_t)(maxb ? maxb : 1) * 2u);
        unsigned *sts2 = (unsigned *)malloc((size_t)(maxb ? maxb : 1) * 4u);
        if (!scr || !locs2 || !sts2) { free(scr); free(locs2); free(sts2); free(tmp2); return; }
        for (int b = 0; b < 256; b++) {
            unsigned m = g_c0[b];
            if (m == 0) continue;
            if (m == 1) { unsigned v = *(unsigned *)(tmp2 + offb[b]) & 0xFFFFFFu; a[offw[b]] = v | ((unsigned)b << 24); continue; }
            bucket_phase(a, tmp2 + offb[b], (int)m, scr, a + offw[b], locs2, sts2, stride2b, (unsigned)b << 24);
        }
        free(scr); free(locs2); free(sts2); free(tmp2);
        return;
    }
    unsigned off[257];
    unsigned s = 0;
    for (int b = 0; b < 256; b++) { off[b] = s; s += fill[b]; }
    off[256] = s;
    unsigned maxb = 0;
    for (int b = 0; b < 256; b++) if (fill[b] > maxb) maxb = fill[b];
    unsigned stride2 = (maxb + 255) / 256 + (maxb >> 12) + 64;
    unsigned short *scr = (unsigned short *)malloc(((size_t)stride2 * 256u + 1024u) * 2u);
    unsigned short *locs = (unsigned short *)malloc((size_t)(maxb ? maxb : 1) * 2u);
    unsigned *sts = (unsigned *)malloc((size_t)(maxb ? maxb : 1) * 4u);
    if (!scr || !locs || !sts) { free(scr); free(locs); free(sts); free(tmp); return; }
    for (int b = 0; b < 256; b++) {
        unsigned m = fill[b];
        if (m == 0) continue;
        const unsigned char *tp = tmp + (size_t)b * stride3;
        if (m == 1) { a[off[b]] = (*(const unsigned *)tp & 0xFFFFFFu) | ((unsigned)b << 24); continue; }
        bucket_phase(a, tp, (int)m, scr, a + off[b], locs, sts, stride2, (unsigned)b << 24);
    }
    _mm_sfence();
    free(scr);
    free(locs);
    free(sts);
    free(tmp);
}

//TOKB1pack7Q

CompilationN/AN/ACompile OKScore: N/A

Testcase #18.785 ms1 MB + 748 KBAcceptedScore: 34

Testcase #2999.143 ms669 MB + 452 KBAcceptedScore: 33

Testcase #31.973 s1337 MB + 808 KBAcceptedScore: 33


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