HDU 6155 Subsequence Count
2017-08-21 09:00
441 查看
题目链接:Subsequence Count
题意:给出一个01字符串,有两种操作:1.将区间内的0变成1,1变成0;2.询问区间内有多少个不相同的连续子串。
题解:先考虑如何算出一个01字符串有多少个不相同的子串,很容易得到一个dp转移方程dp[i][0/1]=dp[i−1][0]+dp[i−1][1]+1,简单的证明一下为什么这个方程是不重不漏的。对于末尾加一个0来说,相当于前面所有以0结尾的字符串都变成了结尾>=2个0的串,所有结尾为1的字符串变成了结尾==1个0的串,然后再补上一个0即可。那么很容易看出,我们对于一个区间的查询,实际上就是一个矩阵乘法,而翻转一个区间,则是交换矩阵的第一行和第二行,再交换矩阵的第一列第二列。用线段树维护即可。计算过程可能炸int,用long long保存数值。
题意:给出一个01字符串,有两种操作:1.将区间内的0变成1,1变成0;2.询问区间内有多少个不相同的连续子串。
题解:先考虑如何算出一个01字符串有多少个不相同的子串,很容易得到一个dp转移方程dp[i][0/1]=dp[i−1][0]+dp[i−1][1]+1,简单的证明一下为什么这个方程是不重不漏的。对于末尾加一个0来说,相当于前面所有以0结尾的字符串都变成了结尾>=2个0的串,所有结尾为1的字符串变成了结尾==1个0的串,然后再补上一个0即可。那么很容易看出,我们对于一个区间的查询,实际上就是一个矩阵乘法,而翻转一个区间,则是交换矩阵的第一行和第二行,再交换矩阵的第一列第二列。用线段树维护即可。计算过程可能炸int,用long long保存数值。
#include <bits/stdc++.h> using namespace std; const int N = 100005; const long long MOD = 1000000007; struct Mat{ long long m[3][3]; Mat(){} Mat(int op){ if(op>0){ m[0][0]=m[0][1]=m[0][2]=1; m[1][0]=0;m[1][1]=1;m[1][2]=0; m[2][0]=m[2][1]=0;m[2][2]=1; }else if(op==0){ m[0][0]=1;m[0][1]=m[0][2]=0; m[1][0]=m[1][1]=m[1][2]=1; m[2][0]=m[2][1]=0;m[2][2]=1; }else if(op==-1){ m[0][0]=m[0][1]=m[0][2]=0; m[1][0]=m[1][1]=m[1][2]=0; m[2][0]=m[2][1]=m[2][2]=0; }else{ m[0][0]=1;m[0][1]=m[0][2]=0; m[1][0]=0;m[1][1]=1;m[1][2]=0; m[2][0]=m[2][1]=0;m[2][2]=1; } } Mat operator *(const Mat& rhs){ Mat c(-1); for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) c.m[i][k]+=m[i][j]*rhs.m[j][k]; for(int i=0;i<3;i++) for(int j=0;j<3;j++) c.m[i][j]%=MOD; return c; } void operator =(const Mat& rhs){ for(int i=0;i<3;i++) for(int j=0;j<3;j++) m[i][j]=rhs.m[i][j]; } void Rev(){ for(int i=0;i<3;i++) swap(m[0][i],m[1][i]); for(int i=0;i<3;i++) swap(m[i][0],m[i][1]); } void Print(){ for(int i=0;i<3;i++){ for(int j=0;j<3;j++) cout<<m[i][j]<<' ';cout<<endl; } } }; struct Node{ int l,r,tg; Mat v; }a[N<<2]; char s ; inline void PushUp(int i){ a[i].v=a[i<<1].v*a[i<<1|1].v; } void Build(int i,int l,int r){ a[i].l=l; a[i].r=r; a[i].tg=0; if(l==r){ a[i].v=Mat(s[l]-'0'); return ; } int mid=l+r>>1; Build(i<<1,l,mid); Build(i<<1|1,mid+1,r); PushUp(i); } inline void PushDown(int i){ if(a[i].tg){ a[i<<1].v.Rev(); a[i<<1].tg^=1; a[i<<1|1].v.Rev(); a[i<<1|1].tg^=1; a[i].tg=0; } } void Mul(int i,int l,int r){ if(l<=a[i].l&&a[i].r<=r){ a[i].v.Rev(); a[i].tg^=1; return ; } PushDown(i); if(l<=a[i<<1].r) Mul(i<<1,l,r); if(a[i<<1|1].l<=r) Mul(i<<1|1,l,r); PushUp(i); } Mat Qry(int i,int l,int r){ if(l<=a[i].l&&a[i].r<=r) return a[i].v; PushDown(i); if(r<=a[i<<1].r) return Qry(i<<1,l,r); else if(a[i<<1|1].l<=l) return Qry(i<<1|1,l,r); else return Qry(i<<1,l,r)*Qry(i<<1|1,l,r); } int main(){ int T,n,q,op,x,y; Mat c; scanf("%d",&T); while(T--){ scanf("%d %d %s",&n,&q,s+1); Build(1,1,n); while(q--){ scanf("%d %d %d",&op,&x,&y); if(op==1) Mul(1,x,y); else{ c=Qry(1,x,y); printf("%lld\n",(c.m[0][2]+c.m[1][2])%MOD); } } } return 0; }
相关文章推荐
- Hdu 6155 Subsequence Count 矩阵计算DP+线段树维护
- HDU 6155 Subsequence Count 线段树维护矩阵
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6155 Subsequence Count 矩阵快速幂
- HDU 6155 Subsequence Count [线段树维护矩阵]
- hdu 6155 - Subsequence Count 线段树+dp+矩阵
- HDU 6155 Subsequence Count(dp+线段树)
- hdu 6155 - Subsequence Count
- HDU 6155 Subsequence Count(线段树 dp)
- HDU1159 Common Subsequence
- hdu 1423 Greatest Common Increasing Subsequence(最长公共递增子序列lcis)
- hdu 3336 Count the string dp+KMP(失配函数)
- HDU 6069 Count Divisor 数学+思维
- HDU 1423 Greatest Common Increasing Subsequence
- HDU-1159 Common Subsequence最长公共子序列
- HDU - 3530 Subsequence
- HDU 5528 Count a * b(数论)
- HDU 1423 Greatest Common Increasing Subsequence (LCIS)
- HDU-4472-Count (2012 ACM/ICPC成都现场赛)
- HDU 4472 count(递推)
- HDU 3336 Count the string 后缀数组 或 (KMP + DP)