正解为文艺平衡树维护矩阵,但我打不动,所以打了部分分
首先可以写成dp形式
然后又可以写成矩阵形式
然后矩阵显然支持结合律
所以可以拿线段树维护
#include
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;
}