hdu 6155 - 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]
显然这是线性递推,我们考虑如何用矩阵表示这种递推关系。
下面分别对应加入一个字符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的更多相关文章
- HDU 6155 Subsequence Count 线段树维护矩阵
Subsequence Count Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Oth ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6155 Subsequence Count 矩阵快速幂
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6155 题意: 题解来自:http://www.cnblogs.com/iRedBean/p/73982 ...
- HDU 6155 Subsequence Count (DP、线性代数、线段树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6155 题解 DP+线代好题.(考场上过多时间刚前两题,没怎么想这题--) 首先列出一个DP式: 设\( ...
- 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] + ...
- HDU 6155 Subsequence Count(矩阵乘法+线段树+基础DP)
题意 给定一个长度为 \(n\) 的 \(01\) 串,完成 \(m\) 种操作--操作分两种翻转 \([l,r]\) 区间中的元素.求区间 \([l,r]\) 有多少个不同的子序列. \(1 \le ...
- 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] ...
- ccpc 网络赛 hdu 6155
# ccpc 网络赛 hdu 6155(矩阵乘法 + 线段树) 题意: 给出 01 串,要么询问某个区间内不同的 01 子序列数量,要么把区间翻转. 叉姐的题解: 先考虑怎么算 \(s_1, s_2, ...
- 【hdu 6155】Subsequence Count
题意 给定一个 \(01\) 串 \(S_{1...n}\) 和 \(Q\) 个操作. 操作有 \(2\) 种类型: 1. 将 \([l,r]\) 区间所有数取反(\(0→1,\space 1→0\) ...
- hdu 3530 Subsequence
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3530 Subsequence Description There is a sequence of i ...
随机推荐
- cmd 环境变量设置方法详细解释
cmd设置环境变量可以方便我们bat脚本的运行,但是要注意的是变量只在当前的cmd窗口有作用(局部生效),如果想要设置持久的环境变量需要我们通过两种手段进行设置:一种是直接修改注册表,另一种是通过我的 ...
- Contiki Process概述
本文涉及到的Protothread机制知识,在http://www.cnblogs.com/songdechiu/p/5793717.html 一.进程类型 进程类型主要有协同式(cooperativ ...
- linux命令学习笔记(47):iostat命令
Linux系统中的 iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视. 它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况. ...
- MySQL多个条件以什么表当做主条件表_20161111周五
前两天有事情 停了2天 数据需求:1.活动日期11.8-11.10订单2.单笔订单购买A类产品 B类产品满足68元.且连续3天下单的用户ID 首先第一个条件很简单,主要是第二个条件 第二个条件是 且 ...
- BZOJ_3124_[Sdoi2013]直径_树形DP
BZOJ_3124_[Sdoi2013]直径_树形DP Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵 ...
- poj3017 Cut the Sequence[平衡树+单调队列优化]
这里已经讲得很清楚了. 本質上是決策點與區間最大值有一定關係,於是用单调队列来维护决策集合(而不是常规的),然后在决策集合中选取最小值. 然后觉得这题方法还是很重要的.没写平衡树,用优先队列(堆)来维 ...
- BZOJ3295:[CQOI2011]动态逆序对
浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html 题目传送门:https://www.lydsy.com/JudgeOnline/prob ...
- Poj_1011_Sticks(剪枝)
一.Description 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位.然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度. ...
- Spring之二:Spring AOP概述
一.AOP概念回顾 AOP是Aspect-Oriented Programming(面向方面编程)的简称, 虽然可以利用面向对象的方法可以很好地组织代码,也可以通过继承关系实现代码重用,但是程序中总是 ...
- git学习 7 git每次push都输入用户名 密码
用如下命令改成SSH的方式 git remote rm origin git remote add origin git@github.com:username/repository.git git ...