トピックリンク
http://acm.hdu.edu.cn/showproblem.php?pid=6155
問題の解決策
DP +ライン良い質問を表します。(考えていなかっただけで最初の二つの質問のテストにあまりに多くの時間、どのようにこの問題......)
最初DP記載されている式:セット\(DP [I] [J ] \) セクションを表し\を(私は\)ビットは最後のビットである\(J \)本質的に異なる配列の数(ない最後のものセクション取らなければならない(私は\)\のビット)、転送考える:
仮定を\(a_iを= 0 \) 、次いで\(DP [i]が[0 ] DP 2 \回= [I-1] [0] + DP [ 1-I] [1] -dp [I-1] [0] = 1 + DP [I-1] [0] + DP [I-1] [1] + +1の\)、理由が考えられている\(1 \)への(I-1 \)\シーケンスを、後ろに追加することができる0
追加するのではなく、正確に完成添加した後\(DP [I-1] [0] \) 番目それことを以前に表示され前面に結合された、失わ1
そこ補償一連の上端0
と単一0
; \([1] [1-I] DP [I] DP = \ [1]) 。\(= a_iを1 \。)と管理。
(まあ、私は他のDPの練習があることを知っているが、これは、データ構造を維持する可能性が最も高いです)
何ら変更は、その後、維持する方法を検討していない場合:係合する\(3 \回3 \)行列\ [\ textbf {A} _0 \回\開始{bmatrix} F_0 \\ F_1 \\ 1 \端を{bmatrix} = \始まります{bmatrix} F_0 + F_1 + 1 \\ F_1 \\ 1 \端{bmatrix}、\ textbf {A} _1 \回\開始{bmatrix} F_0 \\ F_1 \\ 1 \端{bmatrix} = \ {始めるbmatrix } F_0 \\ F_0 + F_1 + 1
\\ 1 \端{bmatrix} \] 簡単得る\ RM \ textbf [\ {A } _0 = \開始{bmatrix} 1・1・1 \\ 0&1&0 \\ 0 0 1 \端{bmatrix }、\ RM \ textbf {A
} _1 = \ {bmatrix} 1&0&0 \\ 1・1・1 \\ 0 0 1 \端{bmatrix} \]始める製品保守間隔にセグメントツリーを。
どのように間隔反転を行うには?2つのセグメントツリーを維持しますか?多くの場合、カードであってもよい、より良い方法があります。(これは、この質問の繊細である)
我々は、マトリックスことが判明\(\ textbf {A} _0 \) 交換を介して\(2 \)回線交換\(2 \)カラムマトリックスの操作後になるかもしれ\(\ RM \ textbf {A} _1 \) 、マトリックス(\ \ textbf {A} _1 \) 同じ操作を介しになることがあり、\(\ textbf {A} _0 \) 。
それは、我々は、マトリックス構成されている\ (\ textbf {E} = 0&1&0 \\ 1&0&0 \\ 0 0始める{bmatrix} \&1つの\エンド{bmatrix} \。。。) 、そこされる(\ \ 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} \ )。
したがって、\(\ PROD ^ {R} _ {i = L}(\ textbf {E} \ textbf {T} _i \ textbf {E})= \ textbf {E}(\ PROD ^ R_ {I = } Lとの\ textbf {T} _i)\ textbf {E} \)上記の基本変換に製品マトリックスに直接次いで、!
時間複雑\(O(N \ N-ログ)\) 。
UPD:ちょうど兄の見つかった\(2 \回2 \) 、マトリックスのメンテナンスコマンドについてです\(\ textbf {A} _0 {bmatrix} F_0 + 1 \\ F_1 + 1 \端を{開始\ \回} = bmatrix \ bmatrix開始{+} F_0 F_1 + 2 F_1 +。1つの\\ \ bmatrix終了{} \) 、\(1 \)は同様。私は唯一の神は、ああどこにでもあると言うことができます......
コード
#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;
}