加载中...

等差数列差分

顾名思义,就是在快速进行为序列的某个子数组从左到右加一个等差数列的操作,等差数列的首项 \(s\) 和公差 \(d\) 可以自己设定。

设区间为 \(a[l \backsim r]\),相当于从左到右每个数加上 \(s\)\(s + d\)\(s + 2d\) \(...\) \(s + (r - l)d\)。利用求和的特性,可以将首项 \(s\) 与公差 \(d\) 的加和操作分开处理:对于 \(s\),相当于一次普通差分;对于 \(d\),可以连续做两次差分来生成一个二阶序列(\(k\) 阶序列可以连续做 \(k\) 次差分得到)。具体实现见下面的例题。

P4231

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define fr first
#define se second
#define endl '\n'
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define int long long 

const int maxn = 1e7 + 5;
ll d1[maxn], d2[maxn];

signed main()
{
    int n, m;
    scanf("%lld%lld", &n, &m);
    for(int t = 1; t <= m; t ++){
        int l, r, s, e;
        scanf("%lld%lld%lld%lld", &l, &r, &s, &e);
        int d = (e - s) / (r - l);
        // !!! 核心 code
        d1[l] += s; d1[r + 1] -= s + (r - l) * d;
        d2[l + 1] += d; d2[r + 1] -= d;
    }

    for(int i = 1; i <= n; i ++){
        d2[i] += d2[i - 1];
    }
    
    // l .......... r      r + 1
    // s s s  ...   s
    // 0 d 2d ... (r-l)*d

    ll xorsum = 0, mx = 0;
    for(int i = 1; i <= n; i ++){
        d1[i] += d1[i - 1];
        d2[i] += d2[i - 1];
        ll res = d1[i] + d2[i];
        xorsum ^= res;
        mx = max(mx, res);
    }

    printf("%lld %lld\n", xorsum, mx);

    return 0;
}
posted @ 2026-01-22 15:33  jxs123  阅读(4)  评论(0)    收藏  举报