题目链接:点击打开链接
题解思路:假设dp[i][1]为到i位置尾部是1个个数有几个,dp[i][0]也是如此,那么假设第i个位置放1,那么dp[i][1] = dp[i-1][1]+dp[i-1][0]+1,dp[i][0] = dp[i-1][0],如果第i个位置放0那么dp[i][0] = dp[i-1][1]+dp[i-1][0]+1,dp[i][1] = dp[i-1][1].我们不妨用矩阵来解决这个问题,那么放1的状态转移矩阵应该是
1 1 1 放0的是 1 0 0
0 1 0 1 1 1
0 0 1, 0 0 1,这里也要注意线段树矩阵合并要右边乘以左边,因为矩阵不满足交换律。还有可以把3*3*3的矩阵乘法优化成2*2*3,毕竟最后一行都是相同的且前两个肯定都是零。
代码:
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int mx = 1e5+10,mod = 1e9+7;
struct data{
ll marx[3][3];
}ma[mx<<2][2];
const data da[2] = {{1,0,0,1,1,1,0,0,1},{1,1,1,0,1,0,0,0,1}};
bool lazy[mx<<2];
char str[mx];
ll ans1,ans2;
int n,m;
void push_up(int rt){
int rt1 = rt<<1,rt2 = rt1|1;
int t1 = lazy[rt1],t2 = lazy[rt2],n1 = t1^1,n2 = t2^1;
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
ll c=0;
for(int k=0;k<2;k++)
c = (c+ma[rt2][t2].marx[i][k]*ma[rt1][t1].marx[k][j]%mod)%mod;
ma[rt][0].marx[i][j] =c;
}
ma[rt][0].marx[i][2] = (ma[rt][0].marx[i][2] + ma[rt2][t2].marx[i][2])%mod;
}
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
ll c=0;
for(int k=0;k<2;k++)
c = (c+ma[rt2][n2].marx[i][k]*ma[rt1][n1].marx[k][j])%mod;
ma[rt][1].marx[i][j] =c;
}
ma[rt][1].marx[i][2] = (ma[rt][1].marx[i][2] + ma[rt2][n2].marx[i][2])%mod;
}
}
void build(int l,int r,int rt){
lazy[rt] = 0;
ma[rt][0].marx[2][2] = ma[rt][1].marx[2][2] = 1;
if(r==l){
int c = str[r]-'0';
ma[rt][0] = da[c],ma[rt][1] = da[c^1];
return ;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
push_up(rt);
}
void push_down(int rt){
if(lazy[rt]){
lazy[rt<<1] ^= 1;
lazy[rt<<1|1] ^= 1;
lazy[rt] = 0;
}
}
void update(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r) { lazy[rt] ^= 1; return ; }
push_down(rt);
int mid = (l+r)>>1;
if(mid>=L) update(L,R,lson);
if(mid<R) update(L,R,rson);
push_up(rt);
}
void query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r){
ll nx,ny;
bool ts = lazy[rt];
nx = ma[rt][ts].marx[0][0]*ans1%mod;
nx = (nx+ma[rt][ts].marx[0][1]*ans2+ma[rt][ts].marx[0][2])%mod;
ny = ma[rt][ts].marx[1][0]*ans1%mod;
ny = (ny+ma[rt][ts].marx[1][1]*ans2+ma[rt][ts].marx[1][2])%mod;
ans1 = nx,ans2 = ny;
return ;
}
int mid = (l+r)>>1;
push_down(rt);
if(mid>=L) query(L,R,lson);
if(mid<R) query(L,R,rson);
push_up(rt);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
scanf("%s",str+1);
build(1,n,1);
while(m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(x&1) update(y,z,1,n,1);
else{
ans1 = ans2 = 0;
query(y,z,1,n,1);
printf("%lld\n",(ans1+ans2)%mod);
}
}
}
return 0;
}