Topic Link
http://acm.hdu.edu.cn/showproblem.php?pid=6155
answer
DP + line represents a good question. (Too much time on the test just the first two questions, did not think how this problem ......)
A formula listed first DP: set \ (dp [i] [j ] \) represents the section \ (I \) bit is the last bit \ (J \) the number of different essentially sequence (not the last one must take the section \ (I \) bits), consider the transfer:
Suppose \ (a_i = 0 \) , then the \ (dp [i] [0 ] = 2 \ times dp [i-1] [0] + dp [ 1-I] [1] -dp [I-1] [0] = 1 + DP [I-1] [0] + DP [I-1] [1] + 1'd \) , the reason is considered \ (1 \) to \ (i-1 \) subsequence, can be added behind a 0
may not be added, but after adding finished exactly \ (dp [i-1] [0] \) th appear earlier that it lose, coupled to the front 1
upper end of the series compensated thereat 0
and a single 0
; \ (DP [I] [. 1] DP = [. 1-I] [. 1] \) . \ (= a_i. 1 \) with management.
(Well, I know that there are other DP practice, but this is most likely to maintain the data structure)
If no modify then consider how to maintain: to engage a \ (3 \ times 3 \) matrix \ [\ textbf {A} _0 \ times \ begin {bmatrix} f_0 \\ f_1 \\ 1 \ end {bmatrix} = \ begin {bmatrix} f_0 + f_1 + 1 \\ f_1 \\ 1 \ end {bmatrix}, \ textbf {A} _1 \ times \ begin {bmatrix} f_0 \\ f_1 \\ 1 \ end {bmatrix} = \ begin {bmatrix } f_0 \\ f_0 + f_1 + 1
\\ 1 \ end {bmatrix} \] easily get \ [\ rm \ textbf {A } _0 = \ begin {bmatrix} 1 & 1 & 1 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \ end {bmatrix }, \ rm \ textbf {A
} _1 = \ begin {bmatrix} 1 & 0 & 0 \\ 1 & 1 & 1 \\ 0 & 0 & 1 \ end {bmatrix} \] segment tree to the product maintenance interval.
Interval inversion how to do? Maintain two segment tree? May be the card often, there is a better way. (This is the subtlety of this question)
we find that the matrix \ (\ textbf {A} _0 \) through exchange \ (2 \) line exchange \ (2 \) after the operation of the column matrix may become \ (\ RM \ textbf {A} _1 \) , matrix \ (\ textbf {A} _1 \) via the same operation may become \ (\ textbf {A} _0 \) .
That is configured we mATRIX \ (\ textbf {E} = \ the begin {bmatrix} 0 &. 1 & 0 \\. 1 & 0 & 0 \\ 0 & 0 &. 1 \ End {bmatrix} \) , then there is \ (\ textbf {E} = \ textbf {E} ^ {-. 1} \) , \ (\ textbf {A} _1 = \ textbf {E} \ textbf {A} _0 \ textbf {E}, \ textbf {A} _0 = \ textbf {E} \ textbf {A} _1 \ textbf {E} \ ) .
therefore \ (\ prod ^ {R} _ {i = L} (\ textbf {E} \ textbf {T} _i \ textbf {E}) = \ textbf {E} (\ prod ^ R_ {i = } L \ textbf {T} _i) \ textbf {E} \) , then directly to the product matrix to elementary transformation of the above!
Time complexity \ (O (n-\ log n-) \) .
UPD: just found a big brother \ (2 \ times 2 \) matrix maintenance, is about command \ (\ textbf {A} _0 \ times \ begin {bmatrix} f_0 + 1 \\ f_1 + 1 \ end { } = bmatrix \ bmatrix the begin {+} f_0 F_1 + 2 F_1 +. 1 \\ \ bmatrix End {} \) , \ (. 1 \) Similarly. I can only say that god is everywhere ah ......
Code
#include<cstdio>
#include<algorithm>
#include<cstring>
#define llong long long
using namespace std;
const int N = 1e5;
const int P = 1e9+7;
void updsum(llong &x,llong y) {x = x+y>=P?x+y-P:x+y;}
struct Matrix
{
llong a[3][3];
Matrix() {a[0][0] = a[0][1] = a[0][2] = a[1][0] = a[1][1] = a[1][2] = a[2][0] = a[2][1] = a[2][2] = 0;}
void unitize() {a[0][0] = a[1][1] = a[2][2] = 1ll; a[0][1] = a[0][2] = a[1][0] = a[1][2] = a[2][0] = a[2][1] = 0ll;}
Matrix operator *(const Matrix &arg) const
{
Matrix ret;
updsum(ret.a[0][0],a[0][0]*arg.a[0][0]%P);
updsum(ret.a[0][0],a[0][1]*arg.a[1][0]%P);
updsum(ret.a[0][0],a[0][2]*arg.a[2][0]%P);
updsum(ret.a[0][1],a[0][0]*arg.a[0][1]%P);
updsum(ret.a[0][1],a[0][1]*arg.a[1][1]%P);
updsum(ret.a[0][1],a[0][2]*arg.a[2][1]%P);
updsum(ret.a[0][2],a[0][0]*arg.a[0][2]%P);
updsum(ret.a[0][2],a[0][1]*arg.a[1][2]%P);
updsum(ret.a[0][2],a[0][2]*arg.a[2][2]%P);
updsum(ret.a[1][0],a[1][0]*arg.a[0][0]%P);
updsum(ret.a[1][0],a[1][1]*arg.a[1][0]%P);
updsum(ret.a[1][0],a[1][2]*arg.a[2][0]%P);
updsum(ret.a[1][1],a[1][0]*arg.a[0][1]%P);
updsum(ret.a[1][1],a[1][1]*arg.a[1][1]%P);
updsum(ret.a[1][1],a[1][2]*arg.a[2][1]%P);
updsum(ret.a[1][2],a[1][0]*arg.a[0][2]%P);
updsum(ret.a[1][2],a[1][1]*arg.a[1][2]%P);
updsum(ret.a[1][2],a[1][2]*arg.a[2][2]%P);
updsum(ret.a[2][0],a[2][0]*arg.a[0][0]%P);
updsum(ret.a[2][0],a[2][1]*arg.a[1][0]%P);
updsum(ret.a[2][0],a[2][2]*arg.a[2][0]%P);
updsum(ret.a[2][1],a[2][0]*arg.a[0][1]%P);
updsum(ret.a[2][1],a[2][1]*arg.a[1][1]%P);
updsum(ret.a[2][1],a[2][2]*arg.a[2][1]%P);
updsum(ret.a[2][2],a[2][0]*arg.a[0][2]%P);
updsum(ret.a[2][2],a[2][1]*arg.a[1][2]%P);
updsum(ret.a[2][2],a[2][2]*arg.a[2][2]%P);
return ret;
}
} trans[2];
char a[N+3];
struct SgTNode
{
Matrix x; bool inv;
} sgt[(N<<2)+3];
void build(int u,int le,int ri)
{
if(le==ri) {sgt[u].x = trans[a[le]]; return;}
int mid = (le+ri)>>1;
build(u<<1,le,mid); build(u<<1|1,mid+1,ri);
sgt[u].x = sgt[u<<1].x*sgt[u<<1|1].x;
}
void maketag(int u)
{
sgt[u].inv ^= 1;
swap(sgt[u].x.a[0][0],sgt[u].x.a[0][1]);
swap(sgt[u].x.a[1][0],sgt[u].x.a[1][1]);
swap(sgt[u].x.a[2][0],sgt[u].x.a[2][1]);
swap(sgt[u].x.a[0][0],sgt[u].x.a[1][0]);
swap(sgt[u].x.a[0][1],sgt[u].x.a[1][1]);
swap(sgt[u].x.a[0][2],sgt[u].x.a[1][2]);
}
void pushdown(int u)
{
if(sgt[u].inv)
{
maketag(u<<1);
maketag(u<<1|1);
sgt[u].inv = 0;
}
}
void inverse(int u,int le,int ri,int lb,int rb)
{
if(le>=lb && ri<=rb) {maketag(u); return;}
pushdown(u);
int mid = (le+ri)>>1;
if(lb<=mid) {inverse(u<<1,le,mid,lb,rb);}
if(rb>mid) {inverse(u<<1|1,mid+1,ri,lb,rb);}
sgt[u].x = sgt[u<<1].x*sgt[u<<1|1].x;
}
Matrix queryprod(int u,int le,int ri,int lb,int rb)
{
if(le>=lb && ri<=rb) {return sgt[u].x;}
pushdown(u);
int mid = (le+ri)>>1; Matrix ret; ret.unitize();
if(lb<=mid) {ret = ret*queryprod(u<<1,le,mid,lb,rb);}
if(rb>mid) {ret = ret*queryprod(u<<1|1,mid+1,ri,lb,rb);}
sgt[u].x = sgt[u<<1].x*sgt[u<<1|1].x;
return ret;
}
int n,q;
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
scanf("%s",a+1); for(int i=1; i<=n; i++) a[i] -= 48;
trans[0].a[0][0] = 1; trans[0].a[0][1] = 1; trans[0].a[0][2] = 1; trans[0].a[1][1] = 1; trans[0].a[2][2] = 1;
trans[1].a[0][0] = 1; trans[1].a[1][0] = 1; trans[1].a[1][1] = 1; trans[1].a[1][2] = 1; trans[1].a[2][2] = 1;
build(1,1,n);
for(int i=1; i<=q; i++)
{
int opt,l,r; scanf("%d%d%d",&opt,&l,&r);
if(opt==1)
{
inverse(1,1,n,l,r);
}
else
{
Matrix ans = queryprod(1,1,n,l,r);
printf("%lld\n",(ans.a[0][2]+ans.a[1][2])%P);
}
}
memset(sgt,0,sizeof(sgt));
}
return 0;
}