zoukankan      html  css  js  c++  java
  • HDU 6155 Subsequence Count 线段树维护矩阵

    Subsequence Count

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others)

    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 typel 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.
     
    Sample Input
    2 4 4 1010 2 1 4 2 2 4 1 2 3 2 1 4 4 4 0000 1 1 2 1 2 3 1 3 4 2 1 4
     
    Sample Output
    11 6 8 10
     
    题解:
      设定dp[i][0/1] 到第i个字符以0/1结尾的子序列方案
      若s[i] = =1 : dp[i][1] = dp[i-1][0] + dp[i-1][1] + 1;
            dp[i][0] = dp[i-1][0];
           若是s[i] == 0: dp[i][0] =  dp[i-1][0] + dp[i-1][1] + 1;
            dp[i][1] = dp[i-1][1];
      写成矩阵,用线段树维护一段连续矩阵乘积,有点卡常数
    #include<bits/stdc++.h>
    using namespace std;
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    typedef unsigned long long ULL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N=5e5+20,M=1e6+10,inf=2147483647;
    
    inline LL read(){
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const LL mod = 1e9+7;
    char s[N];
    
    struct Matix {
        LL arr[3][3];
    }E,F,again,EE;
    inline Matix mul(Matix a,Matix b) {
        Matix ans;
        memset(ans.arr,0,sizeof(ans.arr));
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 3; j++) {
                for(int k = 0; k < 3; k++)
                    ans.arr[i][j] += a.arr[i][k] * b.arr[k][j],ans.arr[i][j] %= mod;
            }
        }
        return ans;
    }
    
    
    Matix v[N * 4],now,facE[N],facF[N];
    int lazy[N * 4],fi[N * 4],se[N * 4];
    
    
    void change(int i) {
        swap(v[i].arr[0][0],v[i].arr[1][0]);
        swap(v[i].arr[0][1],v[i].arr[1][1]);
        swap(v[i].arr[0][2],v[i].arr[1][2]);
        swap(v[i].arr[0][0],v[i].arr[0][1]);
        swap(v[i].arr[1][0],v[i].arr[1][1]);
        swap(v[i].arr[2][0],v[i].arr[2][1]);
    }
    void push_down(int i,int ll,int rr) {
        if(!lazy[i]) return;
        lazy[ls] ^= 1;
        lazy[rs] ^= 1;
        change(ls);change(rs);
        lazy[i] ^= 1;
    }
    inline void push_up(int i,int ll,int rr) {
        v[i] = mul(v[ls],v[rs]);
    }
    void build(int i,int ll,int rr) {
        lazy[i] = 0;
        if(ll == rr) {
            if(s[ll] == '1') v[i] = E,fi[i] = 1,se[i] = 0;
            else v[i] = F,fi[i] = 0,se[i] = 1;
            return ;
        }
        build(ls,ll,mid);
        build(rs,mid+1,rr);
        push_up(i,ll,rr);
    }
    inline void update(int i,int ll,int rr,int x,int y) {
        push_down(i,ll,rr);
        if(ll == x && rr == y) {
            lazy[i] ^= 1;
            change(i);
            return ;
        }
        if(y <= mid) update(ls,ll,mid,x,y);
        else if(x > mid) update(rs,mid+1,rr,x,y);
        else update(ls,ll,mid,x,mid),update(rs,mid+1,rr,mid+1,y);
        push_up(i,ll,rr);
    }
    inline Matix ask(int i,int ll,int rr,int x,int y) {
        push_down(i,ll,rr);
        if(ll == x && rr == y) {
            return v[i];
        }
        if(y <= mid) return ask(ls,ll,mid,x,y);
        else if(x > mid) return ask(rs,mid+1,rr,x,y);
        else return mul(ask(ls,ll,mid,x,mid),ask(rs,mid+1,rr,mid+1,y));
        push_up(i,ll,rr);
    }
    
    int main() {
        EE.arr[0][0] = 1,EE.arr[1][1] = 1,EE.arr[2][2] = 1;
    
        E.arr[0][0] = 1;E.arr[0][1] = 1;E.arr[0][2] = 1;
        E.arr[1][1] = 1;E.arr[2][2] = 1;
    
        F.arr[0][0] = 1;F.arr[1][0] = 1;F.arr[1][1] = 1;
        F.arr[1][2] = 1;F.arr[2][2] = 1;
    
        again.arr[0][2] = 1;
    
        int T;
        T = read();
        while(T--) {
            int n,Q;
            n = read();
            Q = read();
            scanf("%s",s+1);
            build(1,1,n);
            while(Q--) {
                int op,l,r;
                op = read();
                l = read();
                r = read();
                if(op == 1)
                    update(1,1,n,l,r);
                else {
                    now = mul(again,ask(1,1,n,l,r));
                    printf("%lld
    ",(now.arr[0][0]+now.arr[0][1])%mod);
                }
            }
        }
        return 0;
    }
     

    先考虑怎么算 s_1, s_2, ldots, s_ns1,s2,,sn 的答案。设 dp(i, 0/1)dp(i,0/1) 表示考虑到 s_isi,以 0/10/1 结尾的串的数量。那么 dp(i, 0) =dp(i - 1, 0) + dp(i - 1, 1) + 1dp(i,0)=dp(i1,0)+dp(i1,1)+111 也同理。
    那么假设在某个区间之前,dp(i, 0/1) = (x, y)dp(i,0/1)=(x,y) 的话,过了这段区间,就会变成 (ax + by + c, dx + ey + f)(ax+by+c,dx+ey+f) 的形式,只要用线段树维护这个线性变化就好了。

  • 相关阅读:
    [转]CROSS APPLY 和outer apply 的区别
    第一次WCF部署成功心得(UP+证书)
    .NET 简单实现广播
    【转】 c#注册全局快捷键
    软件人才成长链
    [转]关于VS2005智能设备中无法找到PInvoke DLL问题
    [转]我倡导无政府主义编程—Fred George访谈录
    运行Windows Mobile程序时报错:无法找到 PInvoke DLL SQLite.Interop.065.DLL
    系统分析师考试说明
    [转]Oracle 字符集的查看和修改
  • 原文地址:https://www.cnblogs.com/zxhl/p/7405538.html
Copyright © 2011-2022 走看看