线段树维护F[ai-1], F[ai-1 + 1], F[ai-1 - 1], F[ai+1], F[ai+1 + 1], F[ai+1 - 1]
以及两两乘积和
加一的时候可以直接用递推式用保存的F值求出新的值
减一的时候也可以解方程求值
然后 写码农题
然而此题常数太卡 在jzoj上都600ms了 BZ上还是过不去 弃疗了
#include
#include
#include
#include
#include
#define SF scanf
#define PF printf
using namespace std;
typedef int LL;
inline int read() {
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar(); }
return x*f;
}
const int MOD = 1000000007;
const int MAXN = 300000;
int a, b, n, m, inv, L, R, Y, Z;
int p[MAXN+10][4];
int pow_mod(int x, int k) {
int ret = 1;
while(k) {
if(k & 1) ret = 1LL * ret * x % MOD;
x = 1LL * x * x % MOD;
k >>= 1;
}
return ret;
}
struct Matrix {
int a[3][3], r, c;
void set(int n) {
memset(a, 0, sizeof(a));
r = c = n;
for(int i = 0; i < n; i++) a[i][i] = 1;
}
Matrix operator * (const Matrix &t) const {
Matrix ret; memset(ret.a, 0, sizeof(ret.a));
ret.r = r; ret.c = t.c;
for(int i = 0; i < r; i++)
for(int k = 0; k < c; k++)
for(int j = 0; j < 2; j++)
ret.a[i][j] = (ret.a[i][j] + 1LL * a[i][k] * t.a[k][j] % MOD) % MOD;
ret.a[2][2] = 1;
return ret;
}
} A, B, power[40], unit;
Matrix pow_mod(int k) {
Matrix ret = unit;
int i = 1;
while(k) {
if(k & 1) ret = ret * power[i];
k >>= 1;
i++;
}
return ret;
}
void getmat(int i) {
Matrix t = A * pow_mod(p[i][0]-2);
p[i][1] = t.a[0][1]; p[i][2] = t.a[0][0];
}
void build() {
A.r = 1; A.c = 3;
A.a[0][0] = 2; A.a[0][1] = 1; A.a[0][2] = 1;
B.r = B.c = 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++) {
power[i] = B;
B = B * B;
}
}
#define ls (x<<1)
#define rs (x<<1|1)
struct Node {
int s[2][3], ch[3][3], l, r, lz[2];
} t[MAXN*4+10];
inline void up(int x) {
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
t[x].ch[i][j] = (t[ls].ch[i][j] + t[rs].ch[i][j]) % MOD;
for(int i = 0; i < 2; i++)
for(int j = 0; j < 3; j++)
t[x].s[i][j] = (t[ls].s[i][j] + t[rs].s[i][j]) % MOD;
}
inline void add(int x, int l) {
for(int i = 0; i < 2; i++) t[x].s[l][i] = t[x].s[l][i+1];
t[x].s[l][2] = (t[x].s[l][1] + 1LL * t[x].s[l][0] * a + 1LL * b * (t[x].r - t[x].l + 1)) % MOD;
if(l == 0) {
for(int i = 0; i < 2; i++)
for(int j = 0; j < 3; j++)
t[x].ch[i][j] = t[x].ch[i+1][j];
for(int j = 0; j < 3; j++) t[x].ch[2][j] = (t[x].ch[1][j] + 1LL * t[x].ch[0][j] * a+ 1LL * b * t[x].s[1][j]) % MOD;
}
if(l == 1) {
for(int i = 0; i < 3; i++)
for(int j = 0; j < 2; j++)
t[x].ch[i][j] = t[x].ch[i][j+1];
for(int i = 0; i < 3; i++) t[x].ch[i][2] = (t[x].ch[i][1] + 1LL * t[x].ch[i][0] * a + 1LL * b * t[x].s[0][i]) % MOD;
}
}
inline void dec(int x, int l) {
if(a == 0) {
for(int i = 1; i+1; i--) t[x].s[l][i+1] = t[x].s[l][i];
t[x].s[l][0] = (t[x].s[l][1] - 1LL * b * (t[x].r-t[x].l+1) % MOD + MOD) % MOD;
if(l == 0) {
for(int i = 1; i+1; i--)
for(int j = 0; j < 3; j++)
t[x].ch[i+1][j] = t[x].ch[i][j];
for(int i = 0; i < 3; i++) t[x].ch[0][i] = (t[x].ch[1][i] - 1LL * b * t[x].s[1][i] % MOD + MOD) % MOD;
}
else {
for(int i = 1; i+1; i--)
for(int j = 0; j < 3; j++)
t[x].ch[j][i+1] = t[x].ch[j][i];
for(int i = 0; i < 3; i++) t[x].ch[i][0] = (t[x].ch[i][1] - 1LL * b * t[x].s[0][i] % MOD + MOD) % MOD;
}
return ;
}
for(int i = 1; i+1; i--) t[x].s[l][i+1] = t[x].s[l][i];
t[x].s[l][0] = ((t[x].s[l][2] - t[x].s[l][1] - 1LL * b * (t[x].r-t[x].l+1) % MOD) * inv % MOD + MOD) % MOD;
if(l == 0) {
for(int i = 1; i+1; i--)
for(int j = 0; j < 3; j++)
t[x].ch[i+1][j] = t[x].ch[i][j];
for(int i = 0; i < 3; i++) t[x].ch[0][i] = ((t[x].ch[2][i] - t[x].ch[1][i] - 1LL * b * t[x].s[1][i] % MOD) % MOD * inv % MOD + MOD) % MOD;
}
if(l == 1) {
for(int i = 1; i+1; i--)
for(int j = 0; j < 3; j++)
t[x].ch[j][i+1] = t[x].ch[j][i];
for(int i = 0; i < 3; i++) t[x].ch[i][0] = ((t[x].ch[i][2] - t[x].ch[i][1] - 1LL * b * t[x].s[0][i] % MOD) % MOD * inv % MOD + MOD) % MOD;
}
}
inline void pushdown(int x, int y, int z) {
if(z > 0) for(int i = 1; i <= z; i++) add(x, y);
else if(z < 0)
for(int i = -1; i >= z; i--) dec(x, y);
}
inline void pb(int x) {
for(int l = 0; l < 2; l++) {
pushdown(ls, l, t[x].lz[l]);
pushdown(rs, l, t[x].lz[l]);
t[ls].lz[l] += t[x].lz[l];
t[rs].lz[l] += t[x].lz[l];
t[x].lz[l] = 0;
}
}
inline void build(int x, int l, int r) {
Node &u = t[x];
u.l = l; u.r = r;
if(l == r) {
for(int i = 0; i < 3; i++) {
u.s[0][i] = p[l-1][i+1];
u.s[1][i] = p[l+1][i+1];
}
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
u.ch[i][j] = 1LL * u.s[0][i] * u.s[1][j] % MOD;
return ;
}
int mid = l+r >> 1;
build(ls, l, mid);
build(rs, mid+1, r);
up(x);
}
inline void add(int x) {
int l = t[x].l, r = t[x].r;
if(l > R || r < L) return ;
if(L <= l && r <= R) {
t[x].lz[Y] += Z;
pushdown(x, Y, Z);
return ;
}
pb(x);
add(ls);
add(rs);
up(x);
}
inline int que(int x) {
int l = t[x].l, r = t[x].r;
if(l > R || r < L) return 0;
if(L <= l && r <= R) return t[x].ch[2][0];
pb(x);
return (que(ls) + que(rs)) % MOD;
}
int main() {
SF("%d%d%d%d", &n, &m, &a, &b);
inv = pow_mod(a, MOD-2);
unit.set(3);
build();
for(int i = 1; i <= n; i++) {
SF("%d", &p[i][0]);
getmat(i);
p[i][3] = (p[i][2] + 1LL * a * p[i][1] % MOD + b) % MOD;
}
build(1, 2, n-1);
char op[10];
while(m--) {
SF("%s", op);
int l, r;SF("%d%d", &l, &r);
if(op[0] == 'p') {
L = l+1; R = r+1;
Y = 0; Z = 1;
add(1);
L = l-1; R = r-1;
Y = 1; Z = 1;
add(1);
}
else if(op[0] == 'm') {
L = l+1; R = r+1;
Y = 0; Z = -1;
add(1);
L = l-1; R = r-1;
Y = 1; Z = -1;
add(1);
}
else {
L = l+1; R = r-1;
PF("%d\n", que(1));
}
}
}