HDU 6155 Subsequence Count [线段树维护矩阵]
来源:互联网 发布:parallels 没有网络 编辑:程序博客网 时间:2024/05/24 05:36
题意:给你长度为n的01串,m个操作,每次操作有两种
①将区间[L,R]取反(0变1,1变0)
②询问区间[L,R]的所有不同子序列的和
题解:首先我们考虑对于一个01串,我们如何知道它的不同的子序列个数。发现我们可以通过dp来求得
①对于新加入的1来说,dp转移方程为dp[i][1]=dp[i-1][0]+dp[i-1][1]+1;dp[i][0]=dp[i-1][0]。
②对于新加入的0来说,dp转移方程为dp[i][0]=dp[i-1][0]+dp[i-1][1]+1;dp[i][1]=dp[i-1][1]。
从上面的dp转移方程式我们可以得到一个结论:我们可以通过判断新加入字符是0还是1,通过矩阵来表达结果。
例如:
①对于新加入1,我们可以设计这样的矩阵操作。
②对于新加入0,我们可以设计这样的矩阵操作。
当我们需要翻转更新的时候,我们只需要先将矩阵的第一列和第二列交换,再将矩阵的第一行和第一列交换就能得到答案。翻转后打上标记即可。
AC代码:
#include<stdio.h>#include<string.h>#include<algorithm>#define N 100005#define mod 1000000007using namespace std;typedef long long ll;struct Matrix{ll mat[3][3];Matrix(){}Matrix(ll a[3][3]){for(ll i=0;i<3;i++)for(ll j=0;j<3;j++)mat[i][j]=a[i][j];}}tree[N*4],lin,yi,c;ll rev[N*4];char a[100005];ll LIN[3][3]={{1,0,0},{1,1,0},{1,0,1}};ll YI[3][3]={{1,1,0},{0,1,0},{0,1,1}};Matrix multi(Matrix a,Matrix b){memset(c.mat,0,sizeof(c.mat));for(ll i=0;i<3;i++)for(ll j=0;j<3;j++)for(ll k=0;k<3;k++)c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;return c;}void build(ll L,ll R,ll root){if(L==R){if(a[L]=='0')tree[root]=lin;else tree[root]=yi;return ;}ll mid=L+R>>1;build(L,mid,root<<1);build(mid+1,R,root<<1|1);tree[root]=multi(tree[root<<1],tree[root<<1|1]);}void change(Matrix &a){for(ll i=0;i<3;i++)swap(a.mat[i][0],a.mat[i][1]);for(ll i=0;i<3;i++)swap(a.mat[0][i],a.mat[1][i]);}void pushdown(ll root){change(tree[root<<1]);change(tree[root<<1|1]);rev[root<<1]^=1;rev[root<<1|1]^=1;rev[root]=0;}void update(ll l,ll r,ll L,ll R,ll root){if(l<=L&&R<=r){rev[root]^=1;change(tree[root]);return; }if(rev[root])pushdown(root);ll mid=L+R>>1;if(r<=mid)update(l,r,L,mid,root<<1);else if(l>mid)update(l,r,mid+1,R,root<<1|1);else {update(l,mid,L,mid,root<<1);update(mid+1,r,mid+1,R,root<<1|1);}tree[root]=multi(tree[root<<1],tree[root<<1|1]);}Matrix query(ll l,ll r,ll L,ll R,ll root){if(l<=L&&R<=r)return tree[root];if(rev[root])pushdown(root);ll mid=L+R>>1;if(r<=mid)return query(l,r,L,mid,root<<1);else if(l>mid)return query(l,r,mid+1,R,root<<1|1);else return multi(query(l,mid,L,mid,root<<1),query(mid+1,r,mid+1,R,root<<1|1));tree[root]=multi(tree[root<<1],tree[root<<1|1]);}int main(){ll T;scanf("%lld",&T);lin=Matrix(LIN);yi=Matrix(YI);while(T--){memset(tree,0,sizeof(tree));memset(rev,0,sizeof(rev));ll n,m;scanf("%lld%lld",&n,&m);scanf("%s",a+1);build(1,n,1);while(m--){ll op,l,r;scanf("%lld%lld%lld",&op,&l,&r);if(op==1)update(l,r,1,n,1);else {c=query(l,r,1,n,1);printf("%lld\n",(c.mat[2][0]+c.mat[2][1])%mod);}}}}
阅读全文
0 0
- HDU 6155 Subsequence Count [线段树维护矩阵]
- Hdu 6155 Subsequence Count 矩阵计算DP+线段树维护
- HDU 6155 Subsequence Count dp + 矩阵+ 线段树
- HDU 6155 Subsequence Count(线段树 dp)
- Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
- Hdu 6155 线段树维护转移矩阵
- hdu6155-Subsequence Count(线段树+矩阵+dp)
- hdu 5068 线段树维护矩阵乘积
- [HDU 6155] Subsequence Count
- HDU 6155 Subsequence Count
- HDU 5068 Harry And Math Teacher 线段树维护矩阵乘积
- HDU 6155 DP+矩阵+线段树
- HDU 6155 dp+矩阵+线段树
- hdu 6155(线段树+dp+矩阵)
- hdu 2430 线段树维护下标
- hdu 4737 线段树维护+二分
- HDU-5371 Manacher+线段树维护
- hdu 6070 二分+线段树维护
- 字符串左右旋
- RSA host key has changed 错误
- Python基础教程第三章——使用字符串
- CF 429B B.Working out 四个角递推
- 码云--当中私密项目成员如何提交代码
- HDU 6155 Subsequence Count [线段树维护矩阵]
- FastJson将json解析成含有泛型对象,内部泛型对象再次解析出错的解决办法(Android)
- 【C语言】可变参数列表
- 省市、银行支行地址信息
- [第七季]12.遍历元素的后代和同胞
- FAL[server, ARC2]: FAL archival, error 16099 closing archivelog file 'primary'
- JEESZ分布式框架开发环境部署
- Neo4j CQL
- const使用详解