其他分享
首页 > 其他分享> > P1438 无聊的数列

P1438 无聊的数列

作者:互联网

感谢所有AC

传送门

反思

       题目思考量小,此题解关键在于反思。

       不管任何题目都需要在思路已经无法拓展开了才能参考题解!尽可能地保持25分钟以上的思考(尤其是这种蓝绿以上的题目)。

思路

       等差数列很容易引出差分的思路。对于一组等差数列,例如 1 3 5 7 9 来说,其差分数组为 1 2 2 2 2 (-9) ,也就是说等差数列的差分数组是 a d d ... d ,a 为首项,d 为公差。那么题目中的数列可以在差分的状态下进行区间处理,即对于单点 L 来说,需要加上 a ,对于区间 L+1 到 R 需要加上 d ,对于区间 R+1 要减去末项。如何询问单点值?由差分的性质,可知还原数组可以对差分数组进行前缀和,前缀和不就是我们线段树所维护的东西?对于询问 p ,直接访问区间 1 到 p 就可以实现单点查询。

代码 

#include<iostream>
#define maxn 100007
using namespace std;
typedef long long ll;
int n, m, l, r, p, opt, a[maxn], ch[maxn], K, D;
ll t[maxn << 2], lzy[maxn << 2];
void pushup(int u)
{
    t[u] = t[u << 1] + t[(u << 1) + 1];
}
void build(int u, int l, int r)
{
    if (l == r)
        t[u] = ch[l];
    else
    {
        int m = l + r >> 1;
        build(u << 1, l, m), build((u << 1) + 1, m + 1, r);
        pushup(u);
    }
}
void maketag(int u, int len, ll x)
{
    lzy[u] += x;
    t[u] += (ll)len * x;
}
void pushdown(int u, int l, int r)
{
    int m = l + r >> 1;
    maketag(u << 1, m + 1 - l, lzy[u]);
    maketag((u << 1) + 1, r - m, lzy[u]);
    lzy[u] = 0;
}
void update(int u, int l, int r, int L, int R, ll x)
{
    if (L <= l && r <= R)
        maketag(u, r - l + 1, x);
    else if (!(l > R || r < L))
    {
        pushdown(u, l, r);
        int m = l + r >> 1;
        update(u << 1, l, m, L, R, x);
        update((u << 1) + 1, m + 1, r, L, R, x);
        pushup(u);
    }
}
ll query(int u, int l, int r, int L, int R)
{
    if (L <= l && r <= R)
        return t[u];
    else if (!(l > R || r < L))
    {
        pushdown(u, l, r);
        int m = l + r >> 1;
        return query(u << 1, l, m, L, R) + query((u << 1) + 1, m + 1, r, L, R);
    }
    else return 0;
}
void deal(int l, int r, int K, int D)
{
    update(1, 1, n, l, l, K); 
    if (l != r)
        update(1, 1, n, l + 1, r, D);
    if (r + 1 > n)
        return; 
    update(1, 1, n, r + 1, r + 1, -((ll)K + (ll)(r - l) * D));
}
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        ch[i] = a[i] - a[i - 1];
    build(1, 1, n);
    while (m--)
    {
        cin >> opt;
        if (opt == 1)
        {
            cin >> l >> r >> K >> D;
            deal(l, r, K, D);
        }
        else
        {
            cin >> p;
            ll ans = query(1, 1, n, 1, p);
            cout << ans << '\n';
        }
    }
    return 0;
}

标签:opt,数列,无聊,ll,cin,差分,int,maxn,P1438
来源: https://www.cnblogs.com/xqk0225/p/16149835.html