HDU 6155 Subsequence Count (DP, linear algebra, segment tree)

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 0may not be added, but after adding finished exactly \ (dp [i-1] [0] \) th appear earlier that it lose, coupled to the front 1upper end of the series compensated thereat 0and 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;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11366163.html