题目:
给定一个长度为的数组,刚开始每一项的值均为0。个操作:
1 l r:数组A中区间的数+1。
2 l r:区间的操作重做一遍。(数据保证小于当前操作编号) 次操作后,输出数组。1e9+7输出。
做法:
由于2操作不会直接作用在数组上。所以我们的关注点在于个操作中所有1操作对应的次数。如果我们知道每个1操作做了几次,设为第个操作的次数,那么差分一下就能得到数组了,具体就是1到m一遍,对所有1操作,然后做一次前缀和。
题目告诉我们2操作只会影响前面操作的次数。所以我们从后往前处理,同样用一次差分就能得到数组,具体就是m到1一遍,对所有的2操作,,因为差分要用到,所以做差分的同时做的后缀和。
所以总共是做2次差分解决问题。
写得没有很清晰。大家可以看看代码理解一下。
代码:
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false), cin.tie(0) #define debug(a) cout << #a ": " << a << endl using namespace std; typedef long long ll; const int N = 1e5 + 7; const ll mod = 1e9 + 7; struct node{ int op, l, r; node(){} node(int op, int l, int r):op(op),l(l),r(r){} }q[N]; ll a[N], b[N]; int main(void){ IOS; int n, m; cin >> n >> m; for (int i = 1; i <= m; ++i){ int op, l, r; cin >> op >> l >> r; q[i] = node(op, l, r); } a[m+1] = 1; for (int i = m; i >= 1; --i){ int op = q[i].op, l = q[i].l, r = q[i].r; a[i] = (a[i]+a[i+1])%mod; if (op == 2) a[r] = (a[r]+a[i])%mod, a[l-1] = ((a[l-1]-a[i])%mod+mod)%mod; } for (int i = 1; i <= m; ++i){ int op = q[i].op, l = q[i].l, r = q[i].r; if (op == 1) b[l] = (b[l]+a[i])%mod, b[r+1] = ((b[r+1]-a[i])%mod+mod)%mod; } for (int i = 1; i <= n; ++i){ b[i] = (b[i]+b[i-1])%mod; cout << b[i] << ' '; } return 0; }