HDU.6155.Subsequence Count(线段树 矩阵)

题目链接
首先考虑询问[1,n]怎么做
设 f[i][0/1]表示[1,i]以0/1结尾的不同子序列个数
则\(if(A[i]) f[i][1] = f[i-1][0] + f[i-1][1] + 1 , f[i][0] = f[i-1][0]\)
\(\ \ if(!A[i]) f[i][0] = f[i-1][0] + f[i-1][1] + 1 , f[i][1] = f[i-1][1]\)
很整齐,我们来写成矩阵的样子: \(f[i,0]\ f[i,1]\ 1=f[i-1,0]\ f[i-1,1]\ 1\ *\ M\)
算了不写了。。这儿写比较麻烦 不妨看
最后可得原序列为0/1的位置 分别为两个仅互换1,2行 1,2列的矩阵M[0/1] [l,r]的dp值就是区间矩阵乘积的结果 ans = f[i,0]+fi,1

/*
注: Modify时标记不要改两次--
*/
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define gc() getchar()
const int N=1e5+5,mod=1e9+7;
const int M[2][3][3]={{1,0,0,1,1,0,1,0,1},{1,1,0,0,1,0,0,1,1}};//0 1

int n,m,A[N];
char s[N];
struct Matrix
{
    int mat[3][3];
//  Matrix() {memset(mat,0,sizeof mat);}
    Matrix operator *(const Matrix &a)const
    {
        Matrix res;
        for(int i=0; i<3; ++i)
            for(int j=0; j<3; ++j)
            {
                res.mat[i][j]=0;
                for(int k=0; k<3; ++k)
                    res.mat[i][j] += 1LL*mat[i][k]*a.mat[k][j]%mod,
                    res.mat[i][j] >= mod ? res.mat[i][j]-=mod : 0;//还是喜欢紧凑些--
            }
        return res;
    }
};
struct Seg_Tree
{
    Matrix mat[N<<2];
    bool tag[N<<2];
    inline void PushUp(int rt)
    {
        mat[rt]=mat[rt<<1]*mat[rt<<1|1];
    }
    inline void Init(int rt,int opt)
    {
        for(int i=0; i<3; ++i)
            for(int j=0; j<3; ++j)
                mat[rt].mat[i][j]=M[opt][i][j];
//      if(opt)
//          mat[rt].mat[0][0]=mat[rt].mat[0][1]=mat[rt].mat[1][1]=mat[rt].mat[2][1]=mat[rt].mat[2][2]=1;
//      else
//          mat[rt].mat[0][0]=mat[rt].mat[1][0]=mat[rt].mat[1][1]=mat[rt].mat[2][0]=mat[rt].mat[2][2]=1;
    }
    void Swap(int rt)
    {
//      for(int i=0; i<3; ++i)//swap(Line 1,Line 2)
//          std::swap(mat[rt].mat[0][i], mat[rt].mat[1][i]);
//      for(int i=0; i<3; ++i)//swap(Column 1,Column 2)
//          std::swap(mat[rt].mat[i][0], mat[rt].mat[i][1]);
        std::swap(mat[rt].mat[0][0],mat[rt].mat[1][0]),
        std::swap(mat[rt].mat[0][1],mat[rt].mat[1][1]),
        std::swap(mat[rt].mat[0][2],mat[rt].mat[1][2]),
        std::swap(mat[rt].mat[0][0],mat[rt].mat[0][1]),
        std::swap(mat[rt].mat[1][0],mat[rt].mat[1][1]),
        std::swap(mat[rt].mat[2][0],mat[rt].mat[2][1]),
        tag[rt]^=1;
    }
    void PushDown(int rt)
    {
        Swap(rt<<1), Swap(rt<<1|1);
        tag[rt]=0;
    }
    void Build(int l,int r,int rt)
    {
        tag[rt]=0;
        if(l==r)
            if(A[l]) Init(rt,1);
            else Init(rt,0);
        else
        {
            int m=l+r>>1;
            Build(l,m,rt<<1), Build(m+1,r,rt<<1|1);
            PushUp(rt);
        }
    }
    void Modify_Flip(int l,int r,int rt,int L,int R)
    {
        if(L<=l && r<=R) Swap(rt);//, tag[rt]^=1;//WA
        else
        {
            if(tag[rt]) PushDown(rt);
            int m=l+r>>1;
            if(L<=m) Modify_Flip(l,m,rt<<1,L,R);
            if(m<R) Modify_Flip(m+1,r,rt<<1|1,L,R);
            PushUp(rt);
        }
    }
    Matrix Query(int l,int r,int rt,int L,int R)
    {
        if(L<=l && r<=R) return mat[rt];
        if(tag[rt]) PushDown(rt);
        int m=l+r>>1;
        if(L<=m)
            if(m<R) return Query(l,m,rt<<1,L,R)*Query(m+1,r,rt<<1|1,L,R);
            else return Query(l,m,rt<<1,L,R);
        else return Query(m+1,r,rt<<1|1,L,R);
    }
}t;
inline int read()
{
    int now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now*f;
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("1.in","r",stdin);
#endif

    int T=read();
    while(T--)
    {
        n=read(),m=read();
        scanf("%s",s+1);
        for(int i=1; i<=n; ++i) A[i]=s[i]-'0';
        t.Build(1,n,1);
        int opt,l,r; Matrix res;
        while(m--)
        {
            opt=read(),l=read(),r=read();
            if(opt==1) t.Modify_Flip(1,n,1,l,r);
            else
                res = t.Query(1,n,1,l,r),
                printf("%d\n",(res.mat[2][0]+res.mat[2][1])%mod);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/8438012.html

时间: 2024-10-24 15:14:24

HDU.6155.Subsequence Count(线段树 矩阵)的相关文章

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 querie

[HDU6155]Subsequence Count(线段树+矩阵)

DP式很容易得到,发现是线性递推形式,于是可以矩阵加速.又由于是区间形式,所以用线段树维护. https://www.cnblogs.com/Miracevin/p/9124511.html 关键在于证明区间操作中,可以直接在打标记的位置翻转矩阵两行两列. 上面网址用代数形式证了一遍,这里考虑从矩阵本身解释. 由线代内容可知,将一个矩阵作初等行变换,相当于将其左乘一个作了相应初等列变换的单位矩阵.同理将一个矩阵作初等列变换,相当于将其又乘一个作了相应初等行变换的单位矩阵. 这里,左乘的矩阵$T=

HDU 6155 Subsequence Count(矩阵 + DP + 线段树)题解

题意:01串,操作1:把l r区间的0变1,1变0:操作2:求出l r区间的子序列种数 思路:设DP[i][j]为到i为止以j结尾的种数,假设j为0,那么dp[i][0] = dp[i - 1][1] + dp[i -1][0] (0结尾新串) + dp[i - 1][0] (0结尾旧串) - dp[i - 1][0] (重复) + 1(0本身被重复时去除). 那么可以得到转移时的矩阵 $$ \left( \begin{matrix} dp[i - 1][0] & dp[i - 1][1] &am

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6155 Subsequence Count 矩阵快速幂

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6155 题意: 题解来自:http://www.cnblogs.com/iRedBean/p/7398272.html 先考虑dp求01串的不同子序列的个数. dp[i][j]表示用前i个字符组成的以j为结尾的01串个数. 如果第i个字符为0,则dp[i][0] = dp[i-1][1] + dp[i-1][0] + 1,dp[i][1] = dp[i-1][1] 如果第i个字符为1,则dp[i][1

hdu 6155 -&#160;Subsequence Count

话说这题比赛时候过的好少,连题都没读TOT 先考虑dp求01串的不同子序列的个数. dp[i][j]表示用前i个字符组成的以j为结尾的01串个数. 如果第i个字符为0,则dp[i][0] = dp[i-1][1] + dp[i-1][0] + 1,dp[i][1] = dp[i-1][1] 如果第i个字符为1,则dp[i][1] = dp[i-1][1] + dp[i-1][0] + 1,dp[i][0] = dp[i-1][0] 显然这是线性递推,我们考虑如何用矩阵表示这种递推关系. 下面分别

HDU 1542 Atlantis (线段树求矩阵覆盖面积)

题意:给你n个矩阵求覆盖面积. 思路:看了别人的结题报告 给定一个矩形的左下角坐标和右上角坐标分别为:(x1,y1).(x2,y2),对这样的一个矩形,我们构造两条线段,一条定位在x1,它在y坐标的区间是[y1,y2],并且给定一个cover域值为1:另一条线段定位在x2,区间一样是[y1,y2],给定它一个cover值为-1.根据这样的方法对每个矩形都构造两个线段,最后将所有的线段根据所定位的x从左到右进行排序 #include <iostream> #include <stdio.h

HDU 3308 LCIS(线段树)

Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index counting from 0)Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]. Input T in the first line, indicating

HDU 3874 Necklace (线段树单点更新+区间查询+离线操作)

Problem Description Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the same beautiful value, we just count

HDU 3074-Multiply game(线段树:单点更新,区间求积)

Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1450    Accepted Submission(s): 508 Problem Description Tired of playing computer games, alpc23 is planning to play a game on numbe