题目描述
第一行输入数轴长度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; }