【捞】关于线段树
  • 板块学术版
  • 楼主fanypcd
  • 当前回复16
  • 已保存回复16
  • 发布时间2021/10/18 19:06
  • 上次更新2023/11/4 03:22:39
查看原帖
【捞】关于线段树
90027
fanypcd楼主2021/10/18 19:06

第三帖了

RT,线段树维护区间和,平方和,支持区间加和区间对固定数取模(这两个操作其实是固定在一起的,相当于 ai(ai+k)%pa_i \to (a_i + k)\%p 应该可以做到 O(nlogn)O(n\log n) 吧?

但是蒟蒻的算法严重超时了,非常不解。

#pragma GCC optimized(2)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline void read(int &x)
{
    x = 0;
    int f = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        f |= ch == '-';
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - 48;
        ch = getchar();
    }
    x = f ? -x : x;
    return;
}
#define N 500005
int n, q, p, num[N];
struct node
{
    int l, r, val, maxx, tag;
    ll sum;
};
class segment_tree
{
    public:
    node tree[N << 2];
    inline void pushup(int root)
    {
        tree[root].val = tree[root << 1].val + tree[root << 1 | 1].val;
        tree[root].sum = tree[root << 1].sum + tree[root << 1 | 1].sum;
        tree[root].maxx = max(tree[root << 1].maxx, tree[root << 1 | 1].maxx);
        return;
    }
    void build(int root, int l, int r)
    {
        tree[root].l = l;
        tree[root].r = r;
        if(l == r)
        {
            tree[root].val = tree[root].maxx = num[l];
            tree[root].sum = 1ll * num[l] * num[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1, l, mid);
        build(root << 1 | 1, mid + 1, r);
        pushup(root);
        return;
    }
    void addtag(int root, int v)
    {
        tree[root].maxx += v;
        tree[root].sum += 1ll * (tree[root].r - tree[root].l + 1) * v * v + 1ll * 2 * tree[root].val * v;
        tree[root].val += (tree[root].r - tree[root].l + 1) * v;
        tree[root].tag += v;
        return;
    }
    void pushdown(int root)
    {
        if(tree[root].tag)
        {
            addtag(root << 1, tree[root].tag);
            addtag(root << 1 | 1, tree[root].tag);
            tree[root].tag = 0;
        }
        return;
    }
    void updateadd(int root, int L, int R, int v)
    {
        if(L <= tree[root].l && tree[root].r <= R)
        {
            addtag(root, v);
            return;
        }
        pushdown(root);
        int mid = (tree[root].l + tree[root].r) >> 1;
        if(L <= mid)
        {
            updateadd(root << 1, L, R, v);
        }
        if(mid < R)
        {
            updateadd(root << 1 | 1, L, R, v);
        }
        pushup(root);
        return;
    }
    void updatemod(int root, int L, int R)
    {
        if(tree[root].l == tree[root].r)
        {
            tree[root].val %= p;
            tree[root].sum = 1ll * tree[root].val * tree[root].val;
            tree[root].maxx = tree[root].val;
            return;
        }
        pushdown(root);
        if(tree[root].maxx < p)
        {
            return;
        }
        int mid = (tree[root].l + tree[root].r) >> 1;
        if(L <= mid && tree[root << 1].maxx >= p)
        {
            updatemod(root << 1, L, R);
        }
        if(mid < R && tree[root << 1 | 1].maxx >= p)
        {
            updatemod(root << 1 | 1, L, R);
        }
        pushup(root);
        return;
    }
    pair<int, ll> query(int root, int L, int R)
    {
        if(L <= tree[root].l && tree[root].r <= R)
        {
            return make_pair(tree[root].val, tree[root].sum);
        }
        pushdown(root);
        int mid = (tree[root].l + tree[root].r) >> 1;
        pair<int, ll> tmp, ret = make_pair(0, 0ll);
        if(L <= mid)
        {
            tmp = query(root << 1, L, R);
            ret.first += tmp.first, ret.second += tmp.second;
        }
        if(mid < R)
        {
            tmp = query(root << 1 | 1, L, R);
            ret.first += tmp.first, ret.second += tmp.second;
        }
        return ret;
    }
};
segment_tree T;
signed main()
{
//  freopen("pockets.in", "r", stdin);
//  freopen("pockets.out", "w", stdout);
    srand(time(0));
    std::mt19937 rng(rand());
    std::uniform_int_distribution<int> rd(1, 1e9);
    read(n), read(q), read(p);
    for(int i = 1; i <= n; i++)
    {
        read(num[i]);
    }
    T.build(1, 1, n);
    int opt, x, y, v, len;
    while(q--)
    {
        read(opt);
        switch(opt)
        {
            case 1:
            {
                read(x), read(y), read(v);
                T.updateadd(1, x, y, v);
                T.updatemod(1, x, y);
                break;
            }
            case 2:
            {
                read(x), read(y), read(v);
                len = rd(rng) % v;
                if((T.query(1, x, x + len) == T.query(1, y, y + len)) && (T.query(1, x + len, x + v - 1) == T.query(1, y + len, y + v - 1)))
                {
                    printf("ye5\n");
                }
                else
                {
                    printf("n0\n");
                }
                break;
            }
            default:
            {
                return -1;
            }
        }
    }
    return 0;
}
2021/10/18 19:06
加载中...