Luogu P1438无聊的数列

洛谷 P1438无聊的数列#

题目链接#

点这里!


题目描述 

#

维护一个数列ai,支持两种操作:

  • 给出一个长度等于 rl+1的等差数列,首项为k 公差为d 并将它对应加到[l,r]范围中的每一个数上。
    即:令al=al+k al+1=al+1+k+d ... ar=ar+k+(rl)d
  • 询问数列的第p个数的值ap.


解题思路

#

我们可以通过等差数列的性质aiai1=d联想到我们可以用差分解决这道题目
我们先定义一个差分数组d[]
将等差数列的每一项都加到[l,r]范围中的每一个数上 等价于
dl + k
di(l<i<r+1) + d
dr+1 - k + (r-l)*d
对于第二个操作,我们对差分数组求一遍前缀和就可以了
因此本题就是一个线段树的模板题


AC_CODE#

#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
using namespace std;

typedef long long LL;

const int N = 1e5 + 10;

int n, m;
int arr[N], a[N];

struct Node {
    int l, r;
    LL val, add;
}tr[N * 4];

void pushup(int u) {
    tr[u].val = tr[u << 1].val + tr[u << 1 | 1].val;
}

void pushdown(int u) {
    Node &root = tr[u], &ls = tr[u << 1], &rs = tr[u << 1 | 1];
    ls.add += root.add, ls.val += 1LL * root.add * (ls.r - ls.l + 1);
    rs.add += root.add, rs.val += 1LL * root.add * (rs.r - rs.l + 1);
    root.add = 0;
}

void build(int u, int l, int r) {
    if(l == r) {
        tr[u] = {l, r, a[l]};
    }    
    else {                 
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void update(int u, int l, int r, int d) {
    if(tr[u].l >= l && tr[u].r <= r) {
        tr[u].add += d;
        tr[u].val += 1LL * (tr[u].r - tr[u].l + 1) * d;
    }
    else {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l <= mid) update(u << 1, l, r, d);
        if(r > mid) update(u << 1 | 1, l, r, d);
        pushup(u);
    }
}

LL query(int u, int l, int r) {
    if(tr[u].l >= l && tr[u].r <= r) {
        return tr[u].val;
    }
    else {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        LL res = 0;
        if(l <= mid) res = query(u << 1, l, r);
        if(r > mid) res += query(u << 1 | 1, l, r);
        return res;
    }
}

void solve() {
    cin >> n >> m;
    for(int i = 1; i <= n; i ++ ) {
        cin >> arr[i];
        a[i] = arr[i] - arr[i - 1];
    }
    build(1, 1, n);

    int op, l, r, d, k;

    while(m -- ) {
        cin >> op;
        if(op == 1) {
            cin >> l >> r >> k >> d;
            update(1, l, l, k);
            if(l < r) //注意边界 (被卡了一个多小时
                update(1, l + 1, r, d);
            int p = 0 - k - (r - l) * d;
            if(r != n) //同上 qwq
                update(1, r + 1, r + 1, p);
        }
        else {
            scanf("%d", &k);
            printf("%lld\n", query(1, 1, k));
        }
    }
}
 
signed main() 
{
    solve();
    return 0;
}
posted @   ccz9729  阅读(83)  评论(1编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
主题色彩