P1438 无聊的数列

Posted garen-wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1438 无聊的数列相关的知识,希望对你有一定的参考价值。

只要知道套差分就没难度了。


因为你要区间添加一个等差数列,等差数列做差分的话,中间的值是一样的。

随便手膜几组数据,就会发现如何处理差分数组了:

  • 对于点(l):加上首项(k)

  • 对于区间((l, r]):加上公差(d)

  • 对于点(r + 1):减掉等差数列的第(n)项。

只要减不要写成加就可以了。。。

既然用了差分,求原数值的话就需要求差分数组的([1, p])的和。

然后就没事了。

代码:

#include<cstdio>

const int maxn = 100005;
struct segTree
{
    int sum, lazy;
} s[maxn << 2];
int n, m;
int a[maxn], diff[maxn];

#define lson (root << 1)
#define rson (root << 1 | 1)
void pushup(int root)
{
    s[root].sum = s[lson].sum + s[rson].sum;
}
void pushdown(int root, int l, int r)
{
    if(s[root].lazy != 0)
    {
        int mid = (l + r) >> 1;
        s[lson].sum += (mid - l + 1) * s[root].lazy;
        s[lson].lazy += s[root].lazy;
        s[rson].sum += (r - mid) * s[root].lazy;
        s[rson].lazy += s[root].lazy;
        s[root].lazy = 0;
    }
}
void build(int root, int l, int r)
{
    if(l == r) s[root].sum = diff[l];
    else
    {
        int mid = (l + r) >> 1;
        build(lson, l, mid);
        build(rson, mid + 1, r);
        pushup(root);
    }
}
void update(int root, int l, int r, int x, int y, int k)
{
    if(r < x || y < l) return;
    if(x <= l && r <= y)
    {
        s[root].sum += (r - l + 1) * k;
        s[root].lazy += k;
        return;
    }
    pushdown(root, l, r);
    int mid = (l + r) >> 1;
    update(lson, l, mid, x, y, k);
    update(rson, mid + 1, r, x, y, k);
    pushup(root);
}
int query(int root, int l, int r, int x, int y)
{
    if(r < x || y < l) return 0;
    if(x <= l && r <= y) return s[root].sum;
    pushdown(root, l, r);
    int mid = (l + r) >> 1;
    return query(lson, l, mid, x, y) + query(rson, mid + 1, r, x, y);
}
int read()
{
    int ans = 0, s = 1;
    char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘)
    {
        if(ch == ‘-‘) s = -1;
        ch = getchar();
    }
    while(ch >= ‘0‘ && ch <= ‘9‘)
    {
        ans = ans * 10 + ch - ‘0‘;
        ch = getchar();
    }
    return s * ans;
}
int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i++)
    {
        a[i] = read();
        diff[i] = a[i] - a[i - 1];
    }
    build(1, 1, n);
    while(m--)
    {
        int opt = read();
        if(opt == 1)
        {
            int l = read(), r = read(), k = read(), d = read();
            // point l += k
            // (l, r] += d
            // point r + 1 -= k + (r - l + 1 - 1) * d
            update(1, 1, n, l, l, k);
            update(1, 1, n, l + 1, r, d);
            update(1, 1, n, r + 1, r + 1, -(k + (r - l) * d));
        }
        else if(opt == 2)
        {
            int p = read();
            printf("%d
", query(1, 1, n, 1, p));
        }
    }
    return 0;
}

以上是关于P1438 无聊的数列的主要内容,如果未能解决你的问题,请参考以下文章

P1438 无聊的数列

[luogu P1438] 无聊的数列

P1438 无聊的数列

洛谷 P1438 无聊的数列

P1438 无聊的数列(差分&线段树)

洛谷 P1438 无聊的数列