话说这题比赛时候过的好少,连题都没读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 + 7;
const int mSize = 3;struct Matrix
{long long v[mSize][mSize];friend Matrix operator* (const Matrix& a, const Matrix& b){Matrix c;for (int i = 0; i < mSize; i++)for (int j = 0; j < mSize; j++){c.v[i][j] = 0;for (int k = 0; 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[2] = {{1, 0, 0, 1, 1, 0, 1, 0, 1}, {1, 1, 0, 0, 1, 0, 0, 1, 1}};Matrix data[100005 << 2];
bool flip[100005 << 2];
char s[100005];void seq_build(int o, int l, int r)
{if (l == r)data[o] = m[s[l] - '0'];else{int mid = (l + r) >> 1;seq_build(o << 1, l, mid);seq_build(o << 1 | 1, mid + 1, r);data[o] = data[o << 1] * data[o << 1 | 1];}flip[o] = false;
}void doFlip(Matrix& mat)
{swap(mat.v[0][0], mat.v[0][1]);swap(mat.v[1][0], mat.v[1][1]);swap(mat.v[2][0], mat.v[2][1]);swap(mat.v[0][0], mat.v[1][0]);swap(mat.v[0][1], mat.v[1][1]);
}void pushdown(int o)
{if (flip[o]){flip[o << 1] ^= flip[o];flip[o << 1 | 1] ^= flip[o];doFlip(data[o << 1]);doFlip(data[o << 1 | 1]);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 {1, 0, 0, 0, 1, 0, 0, 0, 1};int mid = (l + r) >> 1;pushdown(o);return seq_query(o << 1, l, mid, ql, qr) * seq_query(o << 1 | 1, mid + 1, r, ql, qr);
}void seq_flip(int o, int l, int r, int ql, int qr)
{if (ql <= l && r <= qr){flip[o] ^= 1;doFlip(data[o]);return;}if (r < ql || qr < l)return;int mid = (l + r) >> 1;pushdown(o);seq_flip(o << 1, l, mid, ql, qr);seq_flip(o << 1 | 1, mid + 1, r, ql, qr);data[o] = data[o << 1] * data[o << 1 | 1];
}int main()
{int t;scanf("%d", &t);while (t--){int n, q;scanf("%d%d", &n, &q);scanf("%s", s + 1);seq_build(1, 1, n);while (q--){int op, l, r;scanf("%d%d%d", &op, &l, &r);if (op == 1)seq_flip(1, 1, n, l, r);else{Matrix mat = seq_query(1, 1, n, l, r);printf("%I64d\n", (mat.v[2][0] + mat.v[2][1]) % mod);}}}return 0;
}

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

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

转载于:https://www.cnblogs.com/iRedBean/p/7398272.html

hdu 6155 - Subsequence Count相关推荐

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

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

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

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

  3. 【HDU - 6016】Count the Sheep (思维,类似二分图)

    题干: Altough Skipping the class is happy, the new term still can drive luras anxious which is of cour ...

  4. HDU 5878 I Count Two Three

    打表,二分. 满足条件的数字个数不多,可以全部找出来,排个序,每次询问的时候二分一下. #pragma comment(linker, "/STACK:1024000000,10240000 ...

  5. HDU - 3530 Subsequence(单调队列+思维)

    题目链接:点击查看 题目大意:给出一段长度为n的序列,现在给出一个m和一个k,必须满足一段连续区间内的最大值与最小值的差值大于等于m并且小于等于k,问满足条件的连续区间的最大长度 题目分析:一开始看到 ...

  6. HDU 3530 Subsequence

    这道题很有意思,需要巧妙地套用单调队列 首先我们要明确几件事情 1.假设我们现在知道序列(i,j)是符合标准的,那么如果第j+1个元素不比(i,j)最大值大也不比最小值小,那么(i,j+1)也是合法的 ...

  7. hdu 3530 Subsequence 单调队列

    寻找一个区间,满足:其中的最大值减最小值在[m,k]的范围内,输出最大的区间长度. 思路:维护2个单调队列,一个递增,一个递减. 用一个now记录现在的区间的起点,如果大的数-小的数比k还大,则可以丢 ...

  8. 【XSY2538】/【HDU6155】Subsequence Count(矩阵乘法+线段树)

    题目翻译 Description 给定一个010101串 S1...nS_{1...n}S1...n​ 和 QQQ 个操作. 操作有两种类型: 1.将 [l,r][l,r][l,r] 区间的数取反(将 ...

  9. 【HDU】3441 Rotation

    题意:给出A和C(1<=A,C<=10^9),所有满足B * B * K + 1 = A * A, (K >= 0)的B,构成边长为B的正方形,等角度的围绕在一个小正方形的周围.用C ...

  10. 解题报告 (十三) 尺取法

    文章目录 尺取法 解题报告 PKU 2100 Graveyard Design PKU 3061 Subsequence PKU 2739 Sum of Consecutive Prime Numbe ...

最新文章

  1. 数据科学教育白皮书联合发布!顶级数据人才成长路径
  2. MATLAB使用方法和程序设计,实验1 MATLAB使用方法和程序设计
  3. 物流设计大赛优秀作品_独家!亲历全国大学生物流设计大赛,队员、老师、专家这样说...
  4. DR模式 mysqlABB读写分离
  5. linux内核5.3支持cpu,Linux 5.3版内核重磅发布:支持中国兆芯x86 CPU
  6. head在linux命令中什么意思,linux系统中head命令使用说明
  7. java 线程 获取消息_获取java线程中信息
  8. anaconda安装成功测试_学习笔记120—Win10 成功安装Anaconda 【亲测有效,需注意几点!!!】...
  9. scikit-learn 学习笔记-- Generalized Linear Models (三)
  10. 三、数据预处理——处理分类型数据:编码与哑变量
  11. 计数排序vs基数排序vs桶排序
  12. Android笔记 几条笔记(未实验)
  13. Javascript获取select下拉框选中的的值
  14. php ActiveMQ的安装与使用
  15. 简易学生管理系统(C语言)
  16. C语言终极贪吃蛇代码,直接COPY上手。
  17. 宝藏又小众的室内场景unity3d模型素材网站分享
  18. [iOS]苹果开发证书 一个证书多人开发 注意项
  19. iso 开发学习--简易音乐播放器(基于iPhone4s屏幕尺寸)
  20. 项目如行军——《孙子兵法》之九地篇

热门文章

  1. PopupWindow点击空白区域消失
  2. 常用数据库及表相关操作语句
  3. [转]EntityFramework Core技术线路(EF7已经更名为EF Core,并于2016年6月底发布)
  4. php页面打开响应时间
  5. 图片与路径(Path)的应用
  6. .NET中string[]数组和Liststring泛型的相互转换以及Array类的Sort()方法(转)
  7. 经典代码d359f1d82912ef1b1cd784bd28829325
  8. CentOS下Vim编辑器的使用
  9. 编写可维护的javascript 笔记2(注释)
  10. 老外编辑带你迈出自己容器化的第一步