提交记录 39980


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_dsh_260814 1010. 测测你的四维数点 Accepted 100 622.354 ms 88800 KB C++ 8.67 KB
提交时间 评测时间
2026-08-17 05:01:43 2026-08-17 05:01:46
// 4D strict dominance n=3e5: prefix-bitset B=64 with dim0-canonical reindex (triangle)
// + 2-point AND over dims 1-3 truncated by the dim0 triangle + 2D blocking (counting sort)
// + 4-pass responsibility BF (zero dedup). Prefix stored over bit=pos_0 so pref_0 is the free
// triangle; read only (b0*B)/64 u64s of dims 1-3 => ~3/8 of the 4-dim full-row traffic.
#pragma GCC target("avx2,bmi")
#pragma GCC optimize("O3")
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <sys/mman.h>
#include <immintrin.h>
typedef unsigned u32; typedef unsigned long long u64;
static int order[4][300010];
static int first_pos[4][300010];
static int cnt[300010];
static int ordrank[4][4][300010];
static int ordpos[4][4][300010];
static int pos[4][300010];
static u32 partial[300010];
static u32 corr[300010];
static int proc[300010];
static const unsigned char pc_lut_bytes[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
static inline __m256i pc_bytes(__m256i v){
    const __m256i lut = _mm256_loadu_si256((const __m256i*)pc_lut_bytes);
    const __m256i m4 = _mm256_set1_epi8(0x0F);
    __m256i lo = _mm256_and_si256(v, m4);
    __m256i hi = _mm256_and_si256(_mm256_srli_epi16(v, 4), m4);
    lo = _mm256_shuffle_epi8(lut, lo); hi = _mm256_shuffle_epi8(lut, hi);
    return _mm256_add_epi8(lo, hi);
}
static inline u32 sum4(__m256i v){ return (u32)(_mm256_extract_epi64(v,0)+_mm256_extract_epi64(v,1)+_mm256_extract_epi64(v,2)+_mm256_extract_epi64(v,3)); }
void count_4d(int n, const unsigned *x[4], unsigned *out) {
    int NW = (n + 63) >> 6;
    int NWp = (NW + 7) & ~7;
    const int B = 768;
    int M = (n + B - 1) / B;

    for (int d = 0; d < 4; d++) {
        const unsigned *xd = x[d];
        memset(cnt, 0, sizeof(int) * (n + 1));
        for (int i = 0; i < n; i++) cnt[xd[i]]++;
        int s = 0;
        for (int v = 0; v <= (int)n; v++) { int c = cnt[v]; cnt[v] = s; s += c; }
        for (int i = 0; i < n; i++) first_pos[d][i] = cnt[xd[i]];
        memset(cnt, 0, sizeof(int) * (n + 1));
        for (int i = 0; i < n; i++) cnt[xd[i]]++;
        for (int v = 1; v <= (int)n; v++) cnt[v] += cnt[v-1];
        for (int i = n - 1; i >= 0; i--) order[d][--cnt[xd[i]]] = i;
        for (int t = 0; t < n; t++) pos[d][order[d][t]] = t;
    }
    for (int d = 0; d < 4; d++) {
        for (int a = 0; a < 4; a++)
            for (int t = 0; t < n; t++)
                ordrank[d][a][t] = first_pos[a][order[d][t]];
        for (int a = 0; a < d; a++)
            for (int t = 0; t < n; t++)
                ordpos[d][a][t] = pos[a][order[d][t]];
    }

    // 2D blocking: within dim-0 superblocks, stable counting-sort by first_pos[1].
    const int S = 16384;
    {
        for (int s = 0; s < n; s += S) {
            int e = s + S; if (e > n) e = n;
            memset(cnt, 0, sizeof(int) * (n + 1));
            for (int t = s; t < e; t++) cnt[first_pos[1][order[0][t]]]++;
            for (int v = 1; v <= (int)n; v++) cnt[v] += cnt[v-1];
            for (int t = e - 1; t >= s; t--) {
                int j = order[0][t];
                proc[s + (--cnt[first_pos[1][j]])] = j;
            }
        }
    }

    // Build only dims 1..3, indexed by bit = pos_0 (dim0 position). pref_0 is the free triangle.
    size_t prefsz = (size_t)3 * (M + 1) * NWp * sizeof(u64);
    void *rawp = malloc(prefsz + 64);
    u64 *pref = (u64*)(((size_t)rawp + 63) & ~(size_t)63);
    for (int d = 1; d < 4; d++) {
        u64 *p = pref + (size_t)(d - 1) * (M + 1) * NWp;
        memset(p, 0, (size_t)NWp * sizeof(u64));
        for (int b = 0; b < M; b++) {
            u64 *cur = p + (size_t)(b + 1) * NWp;
            u64 *prev = p + (size_t)b * NWp;
            memcpy(cur, prev, (size_t)NWp * sizeof(u64));
            int e = (b + 1) * B; if (e > n) e = n;
            for (int t = b * B; t < e; t++) {
                int r = ordpos[d][0][t];
                cur[r >> 6] |= 1ULL << (r & 63);
            }
        }
    }
    u64 *p1 = pref;
    u64 *p2 = pref + (size_t)(M + 1) * NWp;
    u64 *p3 = pref + (size_t)2 * (M + 1) * NWp;

    // ---- pass 1: coarse AND + popcount over dims 1-3, truncated by dim0 triangle (2-point) ----
    for (int pos = 0; pos < n; pos += 2) {
        int pa = proc[pos];
        int pb = (pos + 1 < n) ? proc[pos + 1] : -1;
        int Wa = ((first_pos[0][pa] / B) * B) >> 6;
        int Wb = (pb >= 0) ? (((first_pos[0][pb] / B) * B) >> 6) : 0;
        const u64 *qa1 = p1 + (size_t)(first_pos[1][pa] / B) * NWp;
        const u64 *qa2 = p2 + (size_t)(first_pos[2][pa] / B) * NWp;
        const u64 *qa3 = p3 + (size_t)(first_pos[3][pa] / B) * NWp;
        const u64 *qb1 = qa1, *qb2 = qa2, *qb3 = qa3;
        if (pb >= 0) {
            qb1 = p1 + (size_t)(first_pos[1][pb] / B) * NWp;
            qb2 = p2 + (size_t)(first_pos[2][pb] / B) * NWp;
            qb3 = p3 + (size_t)(first_pos[3][pb] / B) * NWp;
        }
        int Wm = Wa < Wb ? Wa : Wb;
        __m256i accA = _mm256_setzero_si256();
        __m256i accB = _mm256_setzero_si256();
        int w = 0;
        for (; w + 4 <= Wm; w += 4) {
            __m256i a1 = _mm256_load_si256((const __m256i*)(qa1 + w));
            __m256i a2 = _mm256_load_si256((const __m256i*)(qa2 + w));
            __m256i a3 = _mm256_load_si256((const __m256i*)(qa3 + w));
            __m256i b1 = _mm256_load_si256((const __m256i*)(qb1 + w));
            __m256i b2 = _mm256_load_si256((const __m256i*)(qb2 + w));
            __m256i b3 = _mm256_load_si256((const __m256i*)(qb3 + w));
            __m256i ra = _mm256_and_si256(a1, _mm256_and_si256(a2, a3));
            __m256i rb = _mm256_and_si256(b1, _mm256_and_si256(b2, b3));
            accA = _mm256_add_epi64(accA, _mm256_sad_epu8(pc_bytes(ra), _mm256_setzero_si256()));
            accB = _mm256_add_epi64(accB, _mm256_sad_epu8(pc_bytes(rb), _mm256_setzero_si256()));
        }
        u32 cA = sum4(accA), cB = sum4(accB);
        for (; w < Wm; w++) {
            cA += (u32)__builtin_popcountll(qa1[w] & qa2[w] & qa3[w]);
            cB += (u32)__builtin_popcountll(qb1[w] & qb2[w] & qb3[w]);
        }
        for (; w < Wa; w++) {
            cA += (u32)__builtin_popcountll(qa1[w] & qa2[w] & qa3[w]);
        }
        int wb = Wm;
        for (; wb < Wb; wb++) {
            cB += (u32)__builtin_popcountll(qb1[wb] & qb2[wb] & qb3[wb]);
        }
        partial[pa] = cA;
        if (pb >= 0) partial[pb] = cB;
    }

    // ---- pass 2: 4-pass responsibility brute force (exact, zero dedup) ----
    memset(corr, 0, sizeof(u32) * n);
    for (int d = 0; d < 4; d++) {
        int e0 = (d == 0) ? 1 : 0;
        int e1 = (d <= 1) ? 2 : 1;
        int e2 = 3 - d;
        if (d == 0) { e0 = 1; e1 = 2; e2 = 3; }
        else if (d == 1) { e0 = 0; e1 = 2; e2 = 3; }
        else if (d == 2) { e0 = 0; e1 = 1; e2 = 3; }
        else { e0 = 0; e1 = 1; e2 = 2; }
        int* A = (e0 < d) ? ordpos[d][e0] : ordrank[d][e0];
        int* B_ = (e1 < d) ? ordpos[d][e1] : ordrank[d][e1];
        int* C = (e2 < d) ? ordpos[d][e2] : ordrank[d][e2];
        int* Dsel = ordrank[d][d];
        for (int t = 0; t < n; t++) {
            int j = order[d][t];
            int f = Dsel[t];
            int bs = (f / B) * B;
            int ta = (e0 < d) ? ((ordrank[d][e0][t] / B) * B) : ordrank[d][e0][t];
            int tb = (e1 < d) ? ((ordrank[d][e1][t] / B) * B) : ordrank[d][e1][t];
            int tc = (e2 < d) ? ((ordrank[d][e2][t] / B) * B) : ordrank[d][e2][t];
            __m256i vta = _mm256_set1_epi32(ta);
            __m256i vtb = _mm256_set1_epi32(tb);
            __m256i vtc = _mm256_set1_epi32(tc);
            int p = bs;
            int cntm = 0;
            for (; p + 16 <= f; p += 16) {
                __m256i a1 = _mm256_loadu_si256((const __m256i*)(A + p));
                __m256i a2 = _mm256_loadu_si256((const __m256i*)(A + p + 8));
                __m256i b1 = _mm256_loadu_si256((const __m256i*)(B_ + p));
                __m256i b2 = _mm256_loadu_si256((const __m256i*)(B_ + p + 8));
                __m256i c1 = _mm256_loadu_si256((const __m256i*)(C + p));
                __m256i c2 = _mm256_loadu_si256((const __m256i*)(C + p + 8));
                __m256i ma = _mm256_and_si256(_mm256_and_si256(_mm256_cmpgt_epi32(vta, a1), _mm256_cmpgt_epi32(vtb, b1)), _mm256_cmpgt_epi32(vtc, c1));
                __m256i mb = _mm256_and_si256(_mm256_and_si256(_mm256_cmpgt_epi32(vta, a2), _mm256_cmpgt_epi32(vtb, b2)), _mm256_cmpgt_epi32(vtc, c2));
                int mask = _mm256_movemask_ps(_mm256_castsi256_ps(ma)) | (_mm256_movemask_ps(_mm256_castsi256_ps(mb)) << 8);
                cntm += __builtin_popcount(mask);
            }
            for (; p < f; p++) {
                if (A[p] < ta && B_[p] < tb && C[p] < tc) cntm++;
            }
            corr[j] += cntm;
        }
    }
    for (int i = 0; i < n; i++) out[i] = partial[i] + corr[i];
    free(rawp);
}

CompilationN/AN/ACompile OKScore: N/A

Testcase #1622.354 ms86 MB + 736 KBAcceptedScore: 100


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