1 solutions

  • 0
    @ 2025-10-12 22:45:37

    代码如下,基本上就是把题目操作暴力地用 avx 相关库实现,注意区间操作上会存在散块,就像提示中说的一样。

    可以简单在这里简单学习一下有关 SIMD 的使用。

    虽然这东西在一般的算法竞赛当中都不让用,但是遇到一些掺入了系统相关的比赛,或许会有用武之地。

    #include <stdio.h>
    #include <algorithm>
    #include <immintrin.h>
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,avx512f,avx512vl,popcnt,tune=native")
    typedef long long i64;
    i64 rd()
    {
        i64 k = 0, f = 1;
        char s = getchar();
        while (s < '0' || s > '9') f = (s == '-') ? 0 : f, s = getchar();
        while (s >= '0' && s <= '9')
            k = (k << 1) + (k << 3) + (s ^ '0'), s = getchar();
        return f ? k : -k;
    }
    void wr(i64 x)
    {
        if (x < 0) putchar('-'), x = -x;
        if (x > 9) wr(x / 10);
        putchar((x % 10) ^ '0');
    }
    const int N = 100010, B = 2, mask = (1 << B) - 1;
    const i64 INF = (i64)1 << 63;
    
    int n, q, blk;
    // 0-index interval : [l, r)
    i64 *a;
    int op, l, r;
    __m256i A[N >> B];
    
    i64 *res;
    __m256i ans;
    
    // add (i-l+1)t to a[i] for (i\in [l, r])
    inline void modify(int l, int r, i64 t)
    {
        i64 l_off = t, r_off = (r - l) * t;
        while ((l & mask) && (l < r)) a[l++] += l_off, l_off += t;
        if (l == r) return;
        while ((r & mask) && (l < r)) a[--r] += r_off, r_off -= t;
        if (l == r) return;
        // notice set_epi64x : 3,2,1,0
        __m256i add = _mm256_set_epi64x(l_off + (t << 1) + t, l_off + (t << 1), l_off + t, l_off); 
        __m256i off = _mm256_set1_epi64x(t << 2);
        for (l >>= B, r >>= B; l < r; ++l) 
            A[l] = _mm256_add_epi64(A[l], add), add = _mm256_add_epi64(add, off);
    }
    inline void _swap(int x, int y)
    {
        i64 tmp = a[x];
        a[x] = a[y], a[y] = tmp;
    }
    // query max a[i] for (i\in [l, r])
    i64 query(int l, int r)
    {
        i64 ret = INF;
        while ((l & mask) && (l < r)) ret = std::max(ret, a[l++]);
        if (l == r) return ret;
        while ((r & mask) && (l < r)) ret = std::max(ret, a[--r]);
        if (l == r) return ret;
    
        ans = _mm256_set1_epi64x(INF);
        for (l >>= B, r >>= B; l < r; ++l) ans = _mm256_max_epi64(ans, A[l]);
        for (int i = 0; i <= mask; ++i) ret = std::max(ret, res[i]);
        return ret;
    }
    int main()
    {
        n = rd(), q = rd(), a = (i64 *)(&A), res = (i64 *)(&ans), blk = (n + mask) >> B;
        for (int i = 0; i < n; ++i) a[i] = rd();
        while (q--)
        {
            op = rd(), l = rd(), r = rd();
            switch (op)
            {
                case 3: modify(l - 1, r, rd()); break;
                case 2: _swap(l - 1, r - 1); break;
                case 1: wr(std::max(query(l - 1, r) - a[0], 0ll)), putchar('\n'); break;
            }
            // for (int i = 0; i < n; ++i, putchar(i == n ? '\n' : ' ')) wr(query(i, i + 1));
        }
    }
    

    Information

    ID
    180
    Time
    1500ms
    Memory
    128MiB
    Difficulty
    7
    Tags
    # Submissions
    13
    Accepted
    1
    Uploaded By