• 黑科技:数组两倍空间线段树,实现方便


    简介

    某天膜 CaptainSlow 代码的时候发现了一个神奇的东西:

    inline void Index(int L, int R) { return L + R | L != R; }
    

    通过这个函数寻找线段树节点的下标只需要两倍空间!不动态开点也可以实现两倍空间!

    luogu 3372

    #include <cstdio>
    #define Maxn 100010
    
    long long T[Maxn << 1], Tag[Maxn << 1], A[Maxn];
    int n, q;
    
    inline int Index(int Left, int Right);
    inline void Build(int Left, int Right);
    inline void Push(int Left, int Right);
    inline void Change(int Left, int Right, int L, int R, long long k);
    inline long long Query(int Left, int Right, int L, int R);
    
    int main() {
        scanf("%d%d", &n, &q);
        for (int i = 1; i <= n; ++i) scanf("%lld", &A[i]);
        Build(1, n);
        for (int i = 1; i <= q; ++i) {
            int opt, x, y;
            scanf("%d%d%d", &opt, &x, &y);
            if (opt == 1) {
                long long k;
                scanf("%lld", &k);
                Change(1, n, x, y, k);
            } else {
                printf("%lld
    ", Query(1, n, x, y));
            }
        }
        return 0;
    }
    
    inline int Index(int Left, int Right) {
        return Left + Right | Left != Right;
    }
    
    inline void Build(int Left, int Right) {
        if (Left == Right) {
            T[Index(Left, Right)] = A[Left];
            return;
        }
        int Mid = (Left + Right) >> 1;
        Build(Left, Mid);
        Build(Mid + 1, Right);
        T[Index(Left, Right)] = T[Index(Left, Mid)] + T[Index(Mid + 1, Right)];
        return;
    }
    
    inline void Push(int Left, int Right) {
        if (Left == Right) return;
        int Mid = (Left + Right) >> 1;
        Tag[Index(Left, Mid)] += Tag[Index(Left, Right)];
        Tag[Index(Mid + 1, Right)] += Tag[Index(Left, Right)];
        T[Index(Left, Mid)] += Tag[Index(Left, Right)] * (Mid - Left + 1);
        T[Index(Mid + 1, Right)] += Tag[Index(Left, Right)] * (Right - Mid);
        Tag[Index(Left, Right)] = 0;
        return;
    }
    
    inline void Change(int Left, int Right, int L, int R, long long k) {
        Push(Left, Right);
        if (L <= Left && Right <= R) {
            Tag[Index(Left, Right)] += k;
            T[Index(Left, Right)] += (Right - Left + 1) * k;
            return;
        }
        int Mid = (Left + Right) >> 1;
        if (L <= Mid) Change(Left, Mid, L, R, k);
        if (R > Mid) Change(Mid + 1, Right, L, R, k);
        T[Index(Left, Right)] = T[Index(Left, Mid)] + T[Index(Mid + 1, Right)];
        return;
    }
    
    inline long long Query(int Left, int Right, int L, int R) {
        Push(Left, Right);
        if (L <= Left && Right <= R) return T[Index(Left, Right)];
        int Mid = (Left + Right) >> 1;
        if (R <= Mid) return Query(Left, Mid, L, R);
        if (L > Mid) return Query(Mid + 1, Right, L, R);
        return Query(Left, Mid, L, R) + Query(Mid + 1, Right, L, R);
    }
    
  • 相关阅读:
    Java实现 LeetCode 371 两整数之和
    Java实现 LeetCode 371 两整数之和
    Java实现 LeetCode 371 两整数之和
    Java实现 LeetCode 1013 将数组分成和相等的三个部分
    Java实现 LeetCode 1013 将数组分成和相等的三个部分
    Java实现 LeetCode 1013 将数组分成和相等的三个部分
    Java实现蓝桥杯VIP算法训练 纪念品分组
    Java实现蓝桥杯VIP算法训练 纪念品分组
    linux下syscall函数,SYS_gettid,SYS_tgkill
    可变参数宏__VA_ARGS__和...
  • 原文地址:https://www.cnblogs.com/chy-2003/p/11815396.html
Copyright © 2020-2023  润新知