题目描述
第一行输入数轴长度n,以及操作次数m,都是1e5的量级。
后面存在m行,第一列是操作数,第二列是 l ,第三列是 r 。
op==1,把数轴 [ l , r ] 中间的点全部+1
op==2,把操作编号是 [ l , r ] 的操作重新执行一遍。
Solution
不看操作2,只看操作1,会发现是个很容易解决的一个差分数组。
如果只看操作2,不看操作1,你也会发现这也是一个差分数组。
现在我们想要交叉的处理两个有关联的差分数组?如何处理?后缀差分!
ans[i] 数组这个表示最后 i 点的点权值。
sum[i] 数组表示第 i 次操作被执行了几次。
很明显之前每次的操作都是被执行了一次的,所以每个初始化sum [ m + 1 ] 都是1,sum [ 0 ] = -1。
很显然如果 sum 数组需要差分维护,并且需要从后往前求后缀数组。
只有从后往前才是无后效性,所以我们需要从后往前枚举操作编号。
如果是操作1,直接把这次操作的 l, r 用正常前缀差分的方法求解这个操作下的 ans数组,因为sum [ i ] 已经被求出来了所以应该比较容易求。
如果是操作2,那就是需要用个后缀差分的办法,再次维护新的 sum 数组。
至于为什么是后缀,我自己的理解是,依次往前推次数就不会遗漏,从前往后推不动这个差分数组。
#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op) putchar(op); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); if (op) putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
inline int lowbit(int x) { return x & (-x); }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 7;
int ans[N], sum[N];
int l[N], r[N], op[N];
int main() {
int n = read(), m = read();
for (int i = 1; i <= m; ++i)
op[i] = read(), l[i] = read(), r[i] = read();
sum[m + 1] = 1;
sum[0] = 0;
for (int i = m; i; --i) {
sum[i] = (sum[i] + sum[i + 1]) % MOD;
if (op[i] == 1)
ans[l[i]] = (ans[l[i]] + sum[i]) % MOD,
ans[r[i] + 1] = (ans[r[i] + 1] - sum[i] + MOD) % MOD;
else
sum[l[i] - 1] = (sum[l[i] - 1] - sum[i] + MOD) % MOD,
sum[r[i]] = (sum[r[i]] + sum[i]) % MOD;
}
int now = 0;
for (int i = 1; i <= n; ++i) {
now = (now + ans[i]) % MOD;
printf("%d%c", now, " \n"[i == n]);
}
return 0;
}

京公网安备 11010502036488号