正解为文艺平衡树维护矩阵,但我打不动,所以打了部分分
首先可以写成dp形式
然后又可以写成矩阵形式
然后矩阵显然支持结合律
所以可以拿线段树维护
#include<bits/stdc++.h>
using namespace std;
#define int long long
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<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
//mt19937 rand(time(0));
//mt19937_64 rand(time(0));
//srand(time(0));
#define N 300010
//#define M
#define mo (int)(1e9+7)
int Mod(int a) {return (a%mo+mo)%mo;
}
struct Martix {int a[4][4]; void mem() {memset(a, 0, sizeof(a)); }void init() {mem(); for(int i=1; i<=3; ++i) a[i][i]=1; }void pre() {mem(); for(int i=1; i<=3; ++i) a[1][i]=1; }int calc() {return (a[1][1]+a[1][2]+a[1][3])%mo; }void print() {printf("ans : %lld %lld %lld\n", a[1][1], a[1][2], a[1][3]); }void print_all() {printf("===\n"); for(int i=1; i<=3; ++i, printf("\n")) for(int j=1; j<=3; ++j) printf("%lld ", a[i][j]); }Martix operator *( Martix &A) {int i, j, k; Martix ans; ans.mem();
// print_all(); A.print_all(); for(i=1; i<=3; ++i)for(j=1; j<=3; ++j)for(k=1; k<=3; ++k)ans.a[i][k]+=a[i][j]*A.a[j][k]%mo, Mod(ans.a[i][k]);
// ans.print_all(); return ans; }
}c[4], ans, ps;
void Pre_Martix() {c[0].a[1][2]=1; c[0].a[1][3]=1; c[0].a[2][3]=1; c[2].a[1][1]=1; c[2].a[1][2]=1; c[2].a[1][3]=1; c[2].a[2][2]=1; c[2].a[2][3]=1; c[2].a[3][3]=1; c[1].a[2][1]=1; c[1].a[3][1]=1; c[1].a[3][2]=1; c[3].a[1][1]=1; c[3].a[2][1]=1; c[3].a[2][2]=1; c[3].a[3][1]=1; c[3].a[3][2]=1; c[3].a[3][3]=1; }
int n, m, i, j, k, T;
int f[N][3], cm[N], q, l, r, rt;
char s[N]; int calc() {ans.pre(); for(i=1; i<n; ++i) {if(cm[i]==1) {if(cm[i]!=cm[i+1]) ans=ans*c[0]; else ans=ans*c[2]; }else {if(cm[i]!=cm[i+1]) ans=ans*c[1]; else ans=ans*c[3]; } }return ans.calc();
}int she1[4]={3, 2, 1, 0};
int she2[4]={2, 3, 0, 1}; struct Segment_tree {int tot, ls[N<<2], rs[N<<2]; Martix s[N<<2], s1[N<<2]; int g[N<<2], stg[N<<2]; void build(int &k, int l, int r) {if(!k) k=++tot, s[k].init(), s1[k].init(); if(l==r) return ;int mid=(l+r)>>1; build(ls[k], l, mid); build(rs[k], mid+1, r); }void push_up(int k) {s[k]=s[ls[k]]*s[rs[k]]; s1[k]=s1[ls[k]]*s1[rs[k]]; }void jia(int k, int y) {s[k]=c[y]; s1[k]=c[y^1]; g[k]=y; }void gai(int k, int *she) {g[k]=she[g[k]]; stg[k]=0; s[k]=c[g[k]]; s1[k]=c[g[k]^1]; }void Qu_gai(int k) {stg[k]^=1; g[k]^=1; swap(s[k], s1[k]); }void push_down(int k) {if(stg[k]) {stg[ls[k]]^=1; stg[rs[k]]^=1; g[ls[k]]^=1; g[rs[k]]^=1; swap(s[ls[k]], s1[ls[k]]); swap(s[rs[k]], s1[rs[k]]); stg[k]=0; }} void add(int k, int l, int r, int x, int y) {if(l==r) return jia(k, y), void(); int mid=(l+r)>>1; if(x<=mid) add(ls[k], l, mid, x, y); else add(rs[k], mid+1, r, x, y); push_up(k); }void Bian(int k, int l, int r, int x, int *she) {if(l==r) return gai(k, she), void(); int mid=(l+r)>>1; push_down(k); if(x<=mid) Bian(ls[k], l, mid, x, she); else Bian(rs[k], mid+1, r, x, she); push_up(k); }void qu(int k, int l, int r, int x, int y) {if(l>=x && r<=y) return Qu_gai(k), void(); int mid=(l+r)>>1; push_down(k); if(x<=mid) qu(ls[k], l, mid, x, y); if(y>=mid+1) qu(rs[k], mid+1, r, x, y); push_up(k); }
}Seg;void suan() { //[1, n-1]for(i=1; i<n; ++i) {if(cm[i]==1) {if(cm[i]!=cm[i+1]) Seg.add(1, 1, n-1, i, 0); else Seg.add(1, 1, n-1, i, 2); }else {if(cm[i]!=cm[i+1]) Seg.add(1, 1, n-1, i, 1); else Seg.add(1, 1, n-1, i, 3); } }
}signed main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);freopen("suffix.in", "r", stdin);freopen("suffix.out", "w", stdout);
// T=read();
// while(T--) {
//
// }n=read(); q=read(); for(i=1; i<n; ++i) cm[i]=read(); cm[n]=0; Pre_Martix(); if (n<=500) {printf("%lld\n", calc()); while(q--) {scanf("%s", s+1); l=read(); r=read(); if(s[1]=='F') {for(i=l; i<=r; ++i) cm[i]^=1; }else {for(i=l, j=r; i<=j; ++i, --j) swap(cm[i], cm[j]); }printf("%lld\n", calc()); }return 0; }Seg.build(rt, 1, n-1); ans.pre(); suan(); ps=ans*Seg.s[1]; printf("%lld\n", ps.calc()); while(q--) {scanf("%s", s+1); l=read(); r=read(); if(s[1]=='F') {if(l-1>=1) Seg.Bian(1, 1, n-1, l-1, she2); if(r<n) Seg.Bian(1, 1, n-1, r, she1); if(l!=r) Seg.qu(1, 1, n-1, l, r-1); }ps=ans*Seg.s[1]; printf("%lld\n", ps.calc()); }return 0;
}