萌新线段树10pts求调
查看原帖
萌新线段树10pts求调
572779
lihugang楼主2024/10/7 21:55

过了样例,只AC了第一个点

#include <stdio.h>
#include <string.h>
#include <utility>

#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)

long long sequence[100008];

typedef struct _node
{
    long long value;
    long long lazyAdd;
} node;

class SegmentTree
{
private:
    node tree[400008];
    int size;

public:
    SegmentTree(long long *sourceData, int sizeOfData)
    {
        size = sizeOfData;
        build(1, size, 1);
    }

    void build(unsigned int left, unsigned int right, unsigned int currentNodeId)
    {
        tree[currentNodeId].lazyAdd = 0;
        if (unlikely(left == right))
            tree[currentNodeId].value = sequence[left];
        else
        {
            auto middle = (left + right) / 2;
            build(left, middle, currentNodeId * 2);
            build(middle + 1, right, currentNodeId * 2 + 1);
            tree[currentNodeId].value = tree[currentNodeId * 2].value + tree[currentNodeId * 2 + 1].value;
        }
    }

    long long getSum(std::pair<unsigned int, unsigned int> queryInterval)
    {
        return getSum(queryInterval, std::make_pair(1, size), 1);
    }

    long long getSum(std::pair<unsigned int, unsigned int> queryInterval, std::pair<unsigned int, unsigned int> currentNodeInterval, unsigned int currentNodeId)
    {
        if (queryInterval.first <= currentNodeInterval.first && queryInterval.second >= currentNodeInterval.second)
        {
            fprintf(stderr, "query[%u, %u], cur->[%u, %u] = %lld\n", queryInterval.first, queryInterval.second, currentNodeInterval.first, currentNodeInterval.second, tree[currentNodeId].value);
            return tree[currentNodeId].value;
        }
        auto middle = (currentNodeInterval.first + currentNodeInterval.second) / 2;
        auto sum = 0ll;

        if (tree[currentNodeId].lazyAdd)
        {
            tree[currentNodeId * 2].value += tree[currentNodeId].lazyAdd * (middle - currentNodeInterval.first + 1);
            tree[currentNodeId * 2 + 1].value += tree[currentNodeId].lazyAdd * (currentNodeInterval.second - middle);
            tree[currentNodeId * 2].lazyAdd += tree[currentNodeId].lazyAdd;
            tree[currentNodeId * 2 + 1].lazyAdd += tree[currentNodeId].lazyAdd;
            tree[currentNodeId].lazyAdd = 0;
        }

        if (queryInterval.first <= middle)
            sum += getSum(queryInterval, std::make_pair(currentNodeInterval.first, middle), currentNodeId * 2);
        if (queryInterval.second > middle)
            sum += getSum(queryInterval, std::make_pair(middle + 1, currentNodeInterval.second), currentNodeId * 2 + 1);

        fprintf(stderr, "query[%u, %u], cur->[%u, %u] = %lld\n", queryInterval.first, queryInterval.second, currentNodeInterval.first, currentNodeInterval.second, sum);
        // printValue();
        // printLazyAdd();
        return sum;
    }

    void update(std::pair<unsigned int, unsigned int> operationInterval, long long changeValue)
    {
        return update(operationInterval, std::make_pair(1, size), 1, changeValue);
    }

    void update(std::pair<unsigned int, unsigned int> operationInterval, std::pair<unsigned int, unsigned int> currentNodeInterval, unsigned int currentNodeId, long long changeValue)
    {
        fprintf(stderr, "change %lld, [%u, %u], cur->[%u, %u] %u\n", changeValue, operationInterval.first, operationInterval.second, currentNodeInterval.first, currentNodeInterval.second, currentNodeId);
        if (unlikely(operationInterval.first <= currentNodeInterval.first && operationInterval.second >= currentNodeInterval.second))
        {
            tree[currentNodeId].value += changeValue * (currentNodeInterval.second - currentNodeInterval.first + 1);
            tree[currentNodeId].lazyAdd += changeValue;
        }
        else
        {
            auto middle = (currentNodeInterval.first + currentNodeInterval.second) / 2;
            if (tree[currentNodeId].lazyAdd && currentNodeInterval.first != currentNodeInterval.second)
            {
                tree[currentNodeId * 2].value += changeValue * (middle - currentNodeInterval.first + 1);
                tree[currentNodeId * 2 + 1].value += changeValue * (currentNodeInterval.second - middle);
                tree[currentNodeId * 2].lazyAdd += tree[currentNodeId].lazyAdd;
                tree[currentNodeId * 2 + 1].lazyAdd += tree[currentNodeId].lazyAdd;
                tree[currentNodeId].lazyAdd = 0;
            }

            if (operationInterval.first <= middle)
                update(operationInterval, std::make_pair(currentNodeInterval.first, middle), currentNodeId * 2, changeValue);
            if (operationInterval.second > middle)
                update(operationInterval, std::make_pair(middle + 1, currentNodeInterval.second), currentNodeId * 2 + 1, changeValue);
            
            tree[currentNodeId].value = tree[currentNodeId * 2].value + tree[currentNodeId * 2 + 1].value;
        }
    }

    void printValue()
    {
        fprintf(stderr, "--value--");
        for (auto &v : tree)
        {
            if (&v == tree + 4*size-5)
                break;
            fprintf(stderr, " %lld", v.value);
        }
        fprintf(stderr, "\n");
    }

    void printLazyAdd()
    {
        fprintf(stderr, "--lazy-add--");
        for (auto &v : tree)
        {
            if (&v == tree + 4*size-5)
                break;
            fprintf(stderr, " %lld", v.lazyAdd);
        }
        fprintf(stderr, "\n");
    }
};

int main()
{
#ifdef DEBUG
    freopen("seg.in", "r", stdin);
#endif
    int countOfNumber, countOfOperations;
    scanf("%d %d", &countOfNumber, &countOfOperations);

    for (auto i = 1; i <= countOfNumber; i++)
        scanf("%lld", &sequence[i]);

    auto segmentTree = new SegmentTree(sequence, countOfNumber);

    for (auto i = 0; i < countOfOperations; i++)
    {
        auto operation = 0u, left = 0u, right = 0u;
        auto changeValue = 0ll;
        scanf("%u", &operation);

        if (operation == 1)
        {
            scanf("%u %u %lld", &left, &right, &changeValue);
            segmentTree->update(std::make_pair(left, right), changeValue);
        }
        else
        {
            scanf("%u %u", &left, &right);
            printf("%lld\n", segmentTree->getSum(std::make_pair(left, right)));
        }
    }
    return 0;
}
2024/10/7 21:55
加载中...