树状数组 && 线段树

树状数组

支持单点修改

#include <cstdio>

using namespace std;

int n, m;
int a[500001], c[500001];

int lowbit(int x)
{
    return x & -x;
}

int sum(int x)
{
    int ans = 0;
    while(x)
    {
        ans += c[x];
        x -= lowbit(x);
    }
    return ans;
}

void add(int x, int d)
{
    while(x <= n)
    {
        c[x] += d;
        x += lowbit(x);
    }
}

int main()
{
    int i, j, x, y, z;
    scanf("%d %d", &n, &m);
    for(i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        add(i, a[i]);
    }
    for(i = 1; i <= m; i++)
    {
        scanf("%d %d %d", &z, &x, &y);
        if(z == 1) add(x, y);
        else printf("%d\n", sum(y) - sum(x - 1));
    }
    return 0;
}
View Code

支持区间修改

#include <cstdio>
#include <iostream>

using namespace std;

int n, m;
long long c0[100001], c1[100001], a[100001];

long long lowbit(int x) {return x & -x;}

long long sum(long long *c, int x)
{
    long long ans = 0;
    while(x)
    {
        ans += c[x];
        x -= lowbit(x);
    }
    return ans;
}

void add(long long *c, int x, int d)
{
    while(x <= n)
    {
        c[x] += d;
        x += lowbit(x);
    }
}

int main()
{
    int i, j, x, y, z, k;
    long long ans;
    scanf("%d%d", &n, &m);
    for(i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        add(c0, i, a[i]);
    }
    for(i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &z, &x, &y);
        if(z == 1)
        {
            scanf("%d", &k);
            add(c0, x, -k * (x - 1));
            add(c1, x, k);
            add(c0, y + 1, k * y);
            add(c1, y + 1, -k);
        }
        else
        {
            ans = 0;
            ans += sum(c0, y) + sum(c1, y) * y;
            ans -= sum(c0, x - 1) + sum(c1, x - 1) * (x - 1);
            printf("%lld\n", ans);
        }
    }
    return 0;
}
View Code

 

线段树

支持区间修改

add[o]表示节点o的lazy标记,且节点o已经修改完

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

#define root 1, 1, N
#define ls o << 1, l, m
#define rs o << 1 | 1, m + 1, r

int L, R;
long long add[1500005], mul[1500005], c[1500005], P;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

inline void pushup(int o)
{
    c[o] = (c[o << 1] + c[o << 1 | 1]) % P;
}

inline void build(int o, int l, int r)
{
    add[o] = 0;
    mul[o] = 1;
    if(l == r)
    {
        scanf("%lld", &c[o]);
        return;
    }
    int m = (l + r) >> 1;
    build(ls);
    build(rs);
    pushup(o);
}

inline void pushdown(int o, int m)
{
    if(add[o] == 0 && mul[o] == 1) return;
    c[o << 1] = (c[o << 1] * mul[o] + add[o] * (m - (m >> 1))) % P;
    c[o << 1 | 1] = (c[o << 1 | 1] * mul[o] + add[o] * (m >> 1)) % P;
    add[o << 1] = (add[o << 1] * mul[o] + add[o]) % P;
    add[o << 1 | 1] = (add[o << 1 | 1] * mul[o] + add[o]) % P;
    mul[o << 1] = (mul[o << 1] * mul[o]) % P;
    mul[o << 1 | 1] = (mul[o << 1 | 1] * mul[o]) % P;
    add[o] = 0;
    mul[o] = 1;
}

inline void update(int f, int d, int o, int l, int r)
{
    if(L <= l && r <= R)
    {
        if(f == 2)
        {
            add[o] = (add[o] + d) % P;
            c[o] = (c[o] + d * (r - l + 1)) % P;
        }
        else
        {
            mul[o] = (mul[o] * d) % P;
            add[o] = (add[o] * d) % P;
            c[o] = (c[o] * d) % P;
        }
        return;
    }
    pushdown(o, r - l + 1);
    int m = (l + r) >> 1;
    if(L <= m) update(f, d, ls);
    if(m < R) update(f, d, rs);
    pushup(o);
}

inline long long query(int o, int l, int r)
{
    if(L <= l && r <= R) return c[o];
    pushdown(o, r - l + 1);
    int m = (l + r) >> 1;
    long long ret = 0;
    if(L <= m) ret += query(ls);
    if(m < R) ret += query(rs);
    return ret;
}

int main()
{
    int N, Q;
    N = read();
    P = read();
    build(root);
    Q = read();
    while(Q--)
    {
        int a, x, y, k;
        a = read();
        if(a == 1 || a == 2)
        {
            x = read();
            y = read();
            k = read();
            L = x;
            R = y;
            update(a, k, root);
        }
        else
        {
            x = read();
            y = read();
            L = x;
            R = y;
            printf("%lld\n", query(root) % P);
        }
    }
    return 0;
}
View Code

 ps:有意思的是这个代码还是[AHOI2009]维护序列的题解

posted @ 2017-03-29 19:19  zht467  阅读(165)  评论(0编辑  收藏  举报