题面及大致思路:,
每个点维护2个矩阵,一共15个变量。矩阵a: [a(i - 1), a(i), a(i + 1); b(i - 1), b(i), b(i + 1)], 矩阵b就是a(i - 1), a(i), a(i + 1)与b(i - 1), b(i), b(i + 1)的两两乘积,矩阵转移的过程很显然,就不细说了。这个题的思维难度不高,就是两点很烦人:1 卡常 2 维护变量很麻烦。
代码:
#include#define ls(x) (x << 1)#define rs(x) ((x << 1) | 1)using namespace std;const int mod = 1000000007;const int maxn = 300010;int c[maxn][4];int a, b, inv;int qpow(int x, int y) { int ans = 1; for(; y; y >>= 1) { if(y & 1) ans = 1ll * ans * x % mod; x = 1ll * x * x % mod; } return ans;}struct Matrix { int a[3][3], n, m; void init(int x) { memset(a, 0, sizeof(a)); n = m = x; for (int i = 0; i < n; i++) a[i][i] = 1; } Matrix operator * (const Matrix &rhs) const { Matrix ret; memset(ret.a, 0, sizeof(ret.a)); ret.n = n, ret.m = rhs.m; for (int i = 0; i < n; i++) for (int k = 0; k < m; k++) for (int j = 0; j < 2; j++) ret.a[i][j] = (ret.a[i][j] + 1ll * a[i][k] * rhs.a[k][j] % mod) % mod; ret.a[2][2] = 1; return ret; }};Matrix A, B, p[35], E;Matrix qpow(int k) { Matrix ans = E; for (int i = 1; k; i++, k >>= 1) { if(k & 1) ans = ans * p[i]; } return ans;}void get_Matrix(int pos) { Matrix tmp = A * qpow(c[pos][0] - 2); c[pos][1] = tmp.a[0][1], c[pos][2] = tmp.a[0][0];}void init_p() { A.n = 1, A.m = 3; A.a[0][0] = 2, A.a[0][1] = 1, A.a[0][2] = 1; B.n = B.m = 3; B.a[0][0] = 1; B.a[1][0] = a, B.a[2][0] = b; B.a[0][1] = 1; B.a[2][2] = 1; for (int i = 1; i <= 32; i++) { p[i] = B; B = B * B; }}struct SegementTree { int sum[2][3], val[3][3], l, r, lz[2];};SegementTree tr[maxn * 4];inline void pushup(int now) { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) tr[now].val[i][j] = (tr[ls(now)].val[i][j] + tr[rs(now)].val[i][j]) % mod; for (int i = 0; i < 2; i++) for (int j = 0; j < 3; j++) tr[now].sum[i][j] = (tr[ls(now)].sum[i][j] + tr[rs(now)].sum[i][j]) % mod;}inline void add1(int now, int flag) { int l = tr[now].l, r = tr[now].r; for (int i = 0; i < 2; i++) tr[now].sum[flag][i] = tr[now].sum[flag][i + 1]; tr[now].sum[flag][2] = (tr[now].sum[flag][1] + 1ll * tr[now].sum[flag][0] * a + 1ll * b * (r - l + 1)) % mod; if(flag == 0) { for (int i = 0; i < 2; i++) for (int j = 0 ; j < 3; j++) tr[now].val[i][j] = tr[now].val[i + 1][j]; for (int j = 0; j < 3; j++) tr[now].val[2][j] = (tr[now].val[1][j] + 1ll * tr[now].val[0][j] * a + 1ll * b * tr[now].sum[1][j]) % mod; } else { for (int i = 0; i < 3; i++) for (int j = 0; j < 2; j++) tr[now].val[i][j] = tr[now].val[i][j + 1]; for (int i = 0; i < 3; i++) tr[now].val[i][2] = (tr[now].val[i][1] + 1ll * tr[now].val[i][0] * a + 1ll * b * tr[now].sum[0][i]) % mod; }}inline void dec1(int now, int flag) { int l = tr[now].l, r = tr[now].r; if(a == 0) { for (int i = 1; i >= 0; i--) tr[now].sum[flag][i + 1] = tr[now].sum[flag][i]; tr[now].sum[flag][0] = (tr[now].sum[flag][1] - 1ll * b * (r - l + 1) % mod + mod) % mod; if(flag == 0) { for (int i = 1; i >= 0; i--) for (int j = 0; j < 3; j++) tr[now].val[i + 1][j] = tr[now].val[i][j]; for (int i = 0; i < 3; i++) tr[now].val[0][i] = (tr[now].val[1][i] - 1ll * b * tr[now].sum[1][i] % mod + mod) % mod; } else { for (int i = 0; i < 3; i++) for (int j = 1; j >= 0; j--) tr[now].val[i][j + 1] = tr[now].val[i][j]; for (int i = 0; i < 3; i++) tr[now].val[i][0] = (tr[now].val[i][1] - 1ll * b * tr[now].sum[0][i] % mod + mod) % mod; } return; } for (int i = 1; i >= 0; i--) tr[now].sum[flag][i + 1] = tr[now].sum[flag][i]; tr[now].sum[flag][0] = ((tr[now].sum[flag][2] - tr[now].sum[flag][1] - 1ll * b * (r - l + 1) % mod) * inv % mod + mod) % mod; if(flag == 0) { for (int i = 1; i >= 0; i--) for (int j = 0; j < 3; j++) tr[now].val[i + 1][j] = tr[now].val[i][j]; for (int i = 0; i < 3; i++) tr[now].val[0][i] = ((tr[now].val[2][i] - tr[now].val[1][i] - 1ll * b * tr[now].sum[1][i] % mod) % mod * inv % mod + mod) % mod; } else { for (int i = 0; i < 3; i++) for (int j = 1; j >= 0; j--) tr[now].val[i][j + 1] = tr[now].val[i][j]; for (int i = 0; i < 3; i++) tr[now].val[i][0] = ((tr[now].val[i][2] - tr[now].val[i][1] - 1ll * b * tr[now].sum[0][i] % mod) % mod * inv % mod + mod) % mod; }}inline void pushdown(int now, int flag, int y) { if(y > 0) for (int i = 1; i <= y; i++) add1(now, flag); else for (int i = -1; i >= y; i--) dec1(now, flag);}inline void Pushdown(int now) { for (int flag = 0; flag < 2; flag++) { pushdown(ls(now), flag, tr[now].lz[flag]); pushdown(rs(now), flag, tr[now].lz[flag]); tr[ls(now)].lz[flag] += tr[now].lz[flag]; tr[rs(now)].lz[flag] += tr[now].lz[flag]; tr[now].lz[flag] = 0; }}inline void build(int now, int l, int r) { tr[now].l = l, tr[now].r = r; if(l == r) { for (int i = 0; i < 3; i++) { tr[now].sum[0][i] = c[l - 1][i + 1]; tr[now].sum[1][i] = c[l + 1][i + 1]; } for (int i = 0; i < 3; i++) for (int j = 0;j < 3; j++) tr[now].val[i][j] = 1ll * tr[now].sum[0][i] * tr[now].sum[1][j] % mod; return; } int mid = (l + r) >> 1; build(ls(now), l, mid); build(rs(now), mid + 1, r); pushup(now);}inline void update(int now, int ql, int qr, int flag,int val) { int l = tr[now].l, r = tr[now].r; if(l > qr || r < ql) return; if(l >= ql && r <= qr) { tr[now].lz[flag] += val; pushdown(now, flag, val); return; } Pushdown(now); int mid = (l + r) >> 1; if(ql <= mid) update(ls(now), ql, qr, flag, val); if(qr > mid) update(rs(now), ql, qr, flag, val); pushup(now);}inline int query(int now, int ql, int qr) { int l = tr[now].l, r = tr[now].r; if(l > qr || r < ql) return 0; if(l >= ql && r <= qr) return tr[now].val[2][0]; Pushdown(now); int mid = (l + r) >> 1; int ans = 0; if(ql <= mid) ans = (ans + query(ls(now), ql, qr)) % mod; if(qr > mid) ans = (ans + query(rs(now), ql, qr)) % mod; return ans;}int main() { int n, m; scanf("%d%d%d%d", &n, &m, &a, &b); inv = qpow(a, mod - 2); E.init(3); init_p(); for (int i = 1; i <= n; i++) { scanf("%d", &c[i][0]); get_Matrix(i); c[i][3] = (c[i][2] + 1ll * a * c[i][1] % mod + b) % mod; } char op[10]; build(1, 2, n - 1); while(m--) { scanf("%s", op + 1); int x, y; scanf("%d%d", &x, &y); if(op[1] == 'p') { update(1, x + 1, y + 1, 0, 1); update(1, x - 1, y - 1, 1, 1); } else if (op[1] == 'm') { update(1, x + 1, y + 1, 0, -1); update(1, x - 1, y - 1, 1, -1); } else { printf("%d\n", query(1, x + 1, y - 1)); } }}