话说这题比赛时候过的好少,连题都没读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]

显然这是线性递推,我们考虑如何用矩阵表示这种递推关系。

下面分别对应加入一个字符0或1时表示递推关系的矩阵。

然后用线段树维护每个区间的矩阵乘积就可以解决查询操作了。

对于修改操作,我们给区间维护一个flip标记,表示该区间是否要翻转,用线段树区间更新的方法去更新flip标记就好了。

将一个区间翻转后,它对应矩阵也要发生改变,这里我们只要将矩阵的第一列与第二列交换后再将第一行与第二行交换就好了。

#include <bits/stdc++.h>
using namespace std; const long long mod = 1e9 + ;
const int mSize = ; struct Matrix
{
long long v[mSize][mSize];
friend Matrix operator* (const Matrix& a, const Matrix& b)
{
Matrix c;
for (int i = ; i < mSize; i++)
for (int j = ; j < mSize; j++)
{
c.v[i][j] = ;
for (int k = ; k < mSize; k++)
c.v[i][j] += a.v[i][k] * b.v[k][j] % mod;
c.v[i][j] %= mod;
}
return c;
}
}; const Matrix m[] = {{, , , , , , , , }, {, , , , , , , , }}; Matrix data[ << ];
bool flip[ << ];
char s[]; void seq_build(int o, int l, int r)
{
if (l == r)
data[o] = m[s[l] - ''];
else
{
int mid = (l + r) >> ;
seq_build(o << , l, mid);
seq_build(o << | , mid + , r);
data[o] = data[o << ] * data[o << | ];
}
flip[o] = false;
} void doFlip(Matrix& mat)
{
swap(mat.v[][], mat.v[][]);
swap(mat.v[][], mat.v[][]);
swap(mat.v[][], mat.v[][]);
swap(mat.v[][], mat.v[][]);
swap(mat.v[][], mat.v[][]);
} void pushdown(int o)
{
if (flip[o])
{
flip[o << ] ^= flip[o];
flip[o << | ] ^= flip[o];
doFlip(data[o << ]);
doFlip(data[o << | ]);
flip[o] = false;
}
} Matrix seq_query(int o, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
return data[o];
if (r < ql || qr < l)
return {, , , , , , , , };
int mid = (l + r) >> ;
pushdown(o);
return seq_query(o << , l, mid, ql, qr) * seq_query(o << | , mid + , r, ql, qr);
} void seq_flip(int o, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
{
flip[o] ^= ;
doFlip(data[o]);
return;
}
if (r < ql || qr < l)
return;
int mid = (l + r) >> ;
pushdown(o);
seq_flip(o << , l, mid, ql, qr);
seq_flip(o << | , mid + , r, ql, qr);
data[o] = data[o << ] * data[o << | ];
} int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n, q;
scanf("%d%d", &n, &q);
scanf("%s", s + );
seq_build(, , n);
while (q--)
{
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if (op == )
seq_flip(, , n, l, r);
else
{
Matrix mat = seq_query(, , n, l, r);
printf("%I64d\n", (mat.v[][] + mat.v[][]) % mod);
}
}
}
return ;
}

----------Update----------

抱歉很久没有看cnblogs了,这里给出一个不太严谨的关于flip部分的证明

hdu 6155 - Subsequence Count的更多相关文章

  1. HDU 6155 Subsequence Count 线段树维护矩阵

    Subsequence Count Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Oth ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6155 题意: 题解来自:http://www.cnblogs.com/iRedBean/p/73982 ...

  3. HDU 6155 Subsequence Count (DP、线性代数、线段树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6155 题解 DP+线代好题.(考场上过多时间刚前两题,没怎么想这题--) 首先列出一个DP式: 设\( ...

  4. 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] + ...

  5. HDU 6155 Subsequence Count(矩阵乘法+线段树+基础DP)

    题意 给定一个长度为 \(n\) 的 \(01\) 串,完成 \(m\) 种操作--操作分两种翻转 \([l,r]\) 区间中的元素.求区间 \([l,r]\) 有多少个不同的子序列. \(1 \le ...

  6. 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] ...

  7. ccpc 网络赛 hdu 6155

    # ccpc 网络赛 hdu 6155(矩阵乘法 + 线段树) 题意: 给出 01 串,要么询问某个区间内不同的 01 子序列数量,要么把区间翻转. 叉姐的题解: 先考虑怎么算 \(s_1, s_2, ...

  8. 【hdu 6155】Subsequence Count

    题意 给定一个 \(01\) 串 \(S_{1...n}\) 和 \(Q\) 个操作. 操作有 \(2\) 种类型: 1. 将 \([l,r]\) 区间所有数取反(\(0→1,\space 1→0\) ...

  9. hdu 3530 Subsequence

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3530 Subsequence Description There is a sequence of i ...

随机推荐

  1. mysql 查看或者修改数据库密码

    首先启动命令行 1.在命令行运行:taskkill /f /im mysqld-nt.exe 下面的操作是操作mysql中bin目录下的一些程序,如果没有配置环境变量的话,需要切换到mysql的bin ...

  2. BZOJ 1609 [Usaco2008 Feb]Eating Together麻烦的聚餐:LIS & LDS (nlogn)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1609 题意: 给你一个只由数字"1,2,3"组成的序列a[i],共n个 ...

  3. laravel基础课程---4、Laravel基础网站结构搭建

    laravel基础课程---4.Laravel基础网站结构搭建 一.总结 一句话总结: 1.搭建网站前后台路由:在路由组Route::group()中设置好命名空间和前缀 2.搭建控制器:比如1)新建 ...

  4. Mybatis中的like模糊查询

    1.  参数中直接加入%% param.setUsername("%CD%");      param.setPassword("%11%"); <sel ...

  5. [原创]Java给word中的table赋值

    一.准备工作: 下载PageOffice for  Java:http://www.zhuozhengsoft.com/dowm/ 二. 实现方法: 要调用PageOffice操作Word中的tabl ...

  6. ECMAScript Obejct 属性操作API

    Object 创建对象 我们有很多种方法创建一个对象,Object.create, Object.assign Object.create //字面量 var o = {}; // 等同于 var o ...

  7. POJ3417Network(LCA+树上查分||树剖+线段树)

    Yixght is a manager of the company called SzqNetwork(SN). Now she's very worried because she has jus ...

  8. @Autowired的作用,自动装配,省去写get/set方法

    这个注解就是spring可以自动帮你把bean里面引用的对象的setter/getter方法省略,它会自动帮你set/get. <bean id="userDao" clas ...

  9. 【Lintcode】095.Validate Binary Search Tree

    题目: Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is define ...

  10. 【LeetCode】047. Permutations II

    题目: Given a collection of numbers that might contain duplicates, return all possible unique permutat ...