Description

筱玛是一个热爱线段树的好筱玛。
筱玛的爷爷马爷在游戏中被筱玛吊打了,于是他恼羞成怒,决定给筱玛出这样一道数据结构题:
给定一个长度为nn的数组AA,刚开始每一项的值均为00。
支持以下两种操作,操作共mm次



mm次操作结束后,你要告诉马爷AA数组变成什么样子了。
由于答案可能会很大,你只需要输出数组AA中的每个数在模意义下的值。

Solution

首先要知道差分是什么(其实我之前也不是很懂)
构造数组 那么
的前缀和
随后对于原数组 的区间修改可以通过差分实现
区间加1就是
这样区间[l, r]内的数字在通过前缀和计算的时候都是原来的数字+1,从而实现区间加的操作

有了这个前置知识,我们把原问题离线处理,从后往前做一个后缀和,判断当前是否是操作1还是操作2,用一个后缀和计算需要的次数即可,具体实现看代码,非常短,最后不要忘记取模。
时间复杂度

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
int l[N], r[N], op[N];
int sum[N], ans[N];
int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  int n, T; cin >> n >> T;
  for(int i = 1; i <= T; i++) {
    cin >> op[i] >> l[i] >> r[i];
  }
  for(int i = T; i >= 1; i--) {
    sum[i] += sum[i + 1], sum[i] %= mod;
    if(op[i] == 1) { // 对原数组区间加
      ans[l[i]] += (1 + sum[i]), ans[l[i]] %= mod;
      ans[r[i] + 1] -= (1 + sum[i]), ans[r[i] + 1] = (ans[r[i] + 1] + mod) % mod;
    } else { // 操作2,对操作次数区间加
      sum[l[i] - 1] -= (sum[i] + 1), sum[l[i] - 1] = (sum[l[i] - 1] + mod) % mod;
      sum[r[i]] += (sum[i] + 1), sum[r[i]] %= mod;
    }
  }
  int now = 0;
  for(int i = 1; i <= n; i++) {
    now += ans[i]; // 前缀和就是原数组
    now %= mod;
    cout << now << " \n"[i == n];
  }
  return 0;
}