1. 程式人生 > >Subsequence Count 2017ccpc網絡賽 1006 dp+線段樹維護矩陣

Subsequence Count 2017ccpc網絡賽 1006 dp+線段樹維護矩陣

const 統計 轉換 inpu mic splay string pen one

Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0‘s and 1‘s), and Q queries on the string.
There are two types of queries:
1. Flipping the bits (i.e., changing all 1 to 0 and 0 to 1) between l and r (inclusive).
2. Counting the number of distinct subsequences in the substring S[l,...,r]
.
Input The first line contains an integer T, denoting the number of the test cases.
For each test, the first line contains two integers N and Q.
The second line contains the string S.
Then Q lines follow, each with three integers type, l and r, denoting the queries.

1T5
1N,Q105
S[i]{0,1},?1iN
type{1,2}

1lrN
Output For each query of type 2, output the answer mod (109+7) in one line.
首先考慮怎麽求一個01串有多少種不同的子序列 dp[i][0]表示考慮到第i位時以0結尾的不同的子序列個數 dp[i][1]表示考慮到第i位時以1結尾的不同的子序列個數 若第i+1位為1,則有: 以01為結尾的子序列個數為dp[i][0] 以11為結尾的子序列個數為dp[i][1] 只有一個1的子序列個數為1 以0為結尾的子序列個數為dp[i][0] 以上4種情況統計了考慮到i+1處時所有的子序列 於是有 dp[i+1][1]=dp[i][0]+dp[i][1]+1
   dp[i+1][0]=dp[i][0]             (1  1  0
(dp[i][0],dp[i][1],1)* 0  1  0 =(dp[i+1][0],dp[i+1][1],1)              0  1  1) 記為A矩陣。 若i+1位為0同理有:         dp[i+1][1]=dp[i][0]     dp[i+1][0]=dp[i][0]+dp[i][1]+1     對應矩陣為(記為B矩陣)           1  0  0                                     1  1  0                          
          1  0  1                           其次考慮優化的問題。將以上的兩種轉移視為矩陣,用線段樹維護矩陣的乘積即可。 對於將所有0換成1,1換成0的操作而言,等價於將所有A矩陣換成B,B換成A,而A和B通過交換1,2行及1,2列可互相轉換,或者說,乘以初等矩陣Fs,t ,該矩陣的逆為自身。(記其為F)                                                             0  1  0                                                                  1  0  0                                                              0  0  1 於是有FAFFAF……FBF……=FAAB……F,或者說,將大量0換成1,1換成0的時候只需要在乘積最外面進行一次交換1,2行與1,2列的操作。 然而。。仍然TLE..估計是被卡了常數。心塞。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int N,Q;
const long long int mo=1e9+7;
char s[5010];
int lazy[5050<<2];
struct Matrix{
    int n,m;
    long long a[3][3];
    Matrix (){clear();}
    void clear(){
        n=m=3;
        memset(a,0,sizeof(a));
    }
    Matrix operator *(const Matrix &b) const{
        Matrix tmp;
        for (int i=0;i<n;++i)
            for (int j=0;j<b.m;++j)
                for (int k=0;k<m;++k)
                    tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*b.a[k][j])%mo;
        return tmp;
    }
};
Matrix A0,A1,E;
Matrix cnt[5050<<2];
inline void init()
{
    A0.a[0][0]=1,A0.a[0][1]=0,A0.a[0][2]=0;
    A0.a[1][0]=1,A0.a[1][1]=1,A0.a[1][2]=0;
    A0.a[2][0]=1,A0.a[2][1]=0,A0.a[2][2]=1;

    A1.a[0][0]=1,A1.a[0][1]=1,A1.a[0][2]=0;
    A1.a[1][0]=0,A1.a[1][1]=1,A1.a[1][2]=0;
    A1.a[2][0]=0,A1.a[2][1]=1,A1.a[2][2]=1;

    E.a[0][0]=1,E.a[0][1]=0,E.a[0][2]=0;
    E.a[1][0]=0,E.a[1][1]=1,E.a[1][2]=0;
    E.a[2][0]=0,E.a[2][1]=0,E.a[2][2]=1;
}
inline void Pushup(int rt)
{
    cnt[rt]=cnt[rt<<1]*cnt[rt<<1|1];
}
inline void build(int l,int r,int rt)
{
    if(l==r)
    {
        if(s[l-1]-0==0)
        {
            cnt[rt]=A0;
        }
        else cnt[rt]=A1;
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    Pushup(rt);
}
inline void change(Matrix &X)
{
    swap(X.a[0][0],X.a[1][1]);
    swap(X.a[0][1],X.a[1][0]);
    swap(X.a[2][0],X.a[2][1]);
}

inline void pushdown(int rt)
{
    if(lazy[rt])
    {
        change(cnt[rt<<1]);
        change(cnt[rt<<1|1]);
        lazy[rt<<1]^=1;
        lazy[rt<<1|1]^=1;
        lazy[rt]=0;
    }
}
inline void update(int a,int b,int l,int r,int rt)
{
    if(l>=a&&r<=b)
    {
        change(cnt[rt]);
        lazy[rt]^=1;
        return;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(a<=m) update(a,b,lson);
    if(b>m) update(a,b,rson);
    Pushup(rt);
}
inline void Input()
{
    scanf("%d%d",&N,&Q);
    scanf("%s",s);
}
inline Matrix query(int a,int b,int l,int r,int rt)
{
    if(l>=a&&r<=b) return cnt[rt];
    pushdown(rt);
    Matrix t1=E,t2=E;
    int m=(r+l)>>1;
    if(a<=m) t1=query(a,b,lson);
    if(b>m) t2=query(a,b,rson);
    return t1*t2;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T,type,l,r;
    scanf("%d",&T);
    init();
    rep(t,1,T)
    {
        Input();
        build(1,N,1);
        rep(i,1,Q)
        {
            scanf("%d%d%d",&type,&l,&r);
            if(type==1)
            {
                update(l,r,1,N,1);
              //  rep(j,1,2*N) printf("i=%d dp%d=%lld\n",i,j,(cnt[j].a[2][0]+cnt[j].a[2][1])%mo);
            }
            else
            {
                Matrix tmp;
                tmp=query(l,r,1,N,1);
                printf("%lld\n",(tmp.a[2][0]+tmp.a[2][1])%mo);
            }
        }
    }
    return 0;
}

代碼如下:

Subsequence Count 2017ccpc網絡賽 1006 dp+線段樹維護矩陣