题目大意:
  给定一个01序列,支持以下两种操作:
    1.区间反转;
    2.区间求不同的子序列数量。

思路:
  首先我们考虑区间反转,这是一个经典的线段树操作。
  接下来考虑求不同的子序列数量,在已知当前区间的情况下,我们有如下$O(n)$的动态规划:|
    $f_{i,0}=f_{i-1,0}+f_{i-1,1}+1,f_{i,1}=f_{i-1,1}//第i位为0$
    $f_{i,1}=f_{i-1,0}+f_{i-1,1}+1,f_{i,0}=f_{i-1,0}//第i位为1$
  这样的动态规划显然无法直接用线段树维护,而如果不能直接用线段树维护,上面维护的区间反转也就失去了意义。
  为了使用线段树维护这种动态规划,我们需要用矩阵表示这种递推关系。
  $\left(\begin{array}{}f_{i+1,0}\\f_{i+1,1}\\1\end{array}\right)=\left(\begin{array}{}f_{i-1,0}\\f_{i-1,1}\\1\end{array}\right)\times\left(\begin{array}{}1&0&0\\1&1&0\\1&0&1\end{array}\right)$
  $\left(\begin{array}{}f_{i+1,0}\\f_{i+1,1}\\1\end{array}\right)=\left(\begin{array}{}f_{i-1,0}\\f_{i-1,1}\\1\end{array}\right)\times\left(\begin{array}{}1&1&0\\0&1&0\\0&1&1\end{array}\right)$
  这样我们就可以保存每个区间的乘积,询问时直接相乘即可。

 #include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
char ch;
while(!isdigit(ch=getchar()));
int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
inline int getdigit() {
char ch;
while(!isdigit(ch=getchar()));
return ch^'';
}
const int N=,mod=1e9+;
template<int SIZE>
struct Matrix {
int val[SIZE][SIZE];
Matrix operator * (const Matrix &another) const {
Matrix ret;
for(int i=;i<SIZE;i++) {
for(int j=;j<SIZE;j++) {
ret.val[i][j]=;
for(int k=;k<SIZE;k++) {
ret.val[i][j]+=(long long)val[i][k]*another.val[k][j]%mod;
ret.val[i][j]%=mod;
}
}
}
return ret;
}
void operator *= (const Matrix &another) {
*this=*this*another;
}
void flip() {
std::swap(val[][],val[][]);
std::swap(val[][],val[][]);
std::swap(val[][],val[][]);
std::swap(val[][],val[][]);
}
int calc() {
return (val[][]+val[][])%mod;
}
};
const Matrix<> m[]={
{,,,
,,,
,,},
{,,,
,,,
,,}
};
const Matrix<> E={
,,,
,,,
,,
};
class SegmentTree {
private:
#define _left <<1
#define _right <<1|1
Matrix<> val[N<<];
bool tag[N<<];
void push_up(const int p) {
val[p]=val[p _left]*val[p _right];
}
void push_down(const int p) {
if(!tag[p]) return;
val[p _left].flip();
val[p _right].flip();
tag[p _left]^=true;
tag[p _right]^=true;
tag[p]=false;
}
public:
void build(const int p,const int b,const int e) {
tag[p]=false;
if(b==e) {
val[p]=m[getdigit()];
return;
}
int mid=(b+e)>>;
build(p _left,b,mid);
build(p _right,mid+,e);
push_up(p);
}
void modify(const int p,const int b,const int e,const int l,const int r) {
if(b==l&&e==r) {
val[p].flip();
tag[p]^=true;
return;
}
push_down(p);
int mid=(b+e)>>;
if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r));
if(r>mid) modify(p _right,mid+,e,std::max(mid+,l),r);
push_up(p);
}
Matrix<> query(const int p,const int b,const int e,const int l,const int r) {
if(b==l&&e==r) {
return val[p];
}
push_down(p);
int mid=(b+e)>>;
Matrix<> ret=E;
if(l<=mid) ret*=query(p _left,b,mid,l,std::min(mid,r));
if(r>mid) ret*=query(p _right,mid+,e,std::max(mid+,l),r);
return ret;
}
};
SegmentTree t;
int main() {
for(int T=getint();T;T--) {
int n=getint(),q=getint();
t.build(,,n);
while(q--) {
int op=getint(),l=getint(),r=getint();
switch(op) {
case : {
t.modify(,,n,l,r);
break;
}
case : {
printf("%d\n",t.query(,,n,l,r).calc());
break;
}
}
}
}
return ;
}

[HDU6155]Subsequence Count的更多相关文章

  1. [HDU6155]Subsequence Count(线段树+矩阵)

    DP式很容易得到,发现是线性递推形式,于是可以矩阵加速.又由于是区间形式,所以用线段树维护. https://www.cnblogs.com/Miracevin/p/9124511.html 关键在于 ...

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

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

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

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

  4. Subsequence Count (线段树)

    Time Limit: 1000 ms   Memory Limit: 256 MB Description 给定一个01串 $S_{1 \cdots n}$ 和 $Q$ 个操作. 操作有两种类型: ...

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

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

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

  7. Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵

    Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries ...

  8. [Contest20171006]Subsequence Count

    给定一个01串$S_{1\cdots n}$和$Q$个操作.操作有两种类型:1.将$[l,r]$区间的数取反(将其中的$0$变成$1$,$1$变成$0$).2.询问字符串$S$的子串$S_{l\cdo ...

  9. hdu 6155 - Subsequence Count

    话说这题比赛时候过的好少,连题都没读TOT 先考虑dp求01串的不同子序列的个数. dp[i][j]表示用前i个字符组成的以j为结尾的01串个数. 如果第i个字符为0,则dp[i][0] = dp[i ...

随机推荐

  1. Interval Minimum Number

    Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. ...

  2. linux音频alsa-uda134x驱动分析之二(时钟)

    Audio Clocking音频时钟============== This text describes the audio clocking terms in ASoC and digital au ...

  3. 对于Linux平台下C语言开发中__sync_函数的认识(转)

    reference:http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html#Atomic-Builtins A built-i ...

  4. ETL利器Kettle实战应用解析系列二

    本系列文章主要索引如下: 一.ETL利器Kettle实战应用解析系列一[Kettle使用介绍] 二.ETL利器Kettle实战应用解析系列二 [应用场景和实战DEMO下载] 三.ETL利器Kettle ...

  5. 虚拟机 ubuntu 16.04

    下载地址:https://www.ubuntu.com/download/desktop 使用虚拟机直接安装

  6. 练习题 --- 10种Xpath定位

    写出10种不同的Xpath定位语法

  7. 淘宝开放平台TOP SDK调用对接淘宝或天猫

    如果在淘宝/天猫上开了网店,用户自己也有一套自己的管理平台,这时可能会考虑和淘宝进行数据对接.这就需要考虑调用阿里提供的开发接口来推送和接收数据. 对接的方式有2种,一种是通过http接口,另外一种是 ...

  8. JMeter接口&性能测试

    JMeter接口测试 目前最新版本发展到5.0版本,需要Java7以上版本环境,下载解压目录后,进入\apache-jmeter-5.0\bin\,双击ApacheJMeter.jar文件启动JMem ...

  9. Effective STL 学习笔记:19 ~ 20

    Effective STL 学习笔记:19 ~ 20 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  10. cve-2010-3333 Microsoft Office Open XML文件格式转换器栈缓冲区溢出漏洞 分析

    用的是泉哥的POC来调的这个漏洞 0x0 漏洞调试    Microsoft Office Open XML文件格式转换器栈缓冲区溢出漏洞 Microsoft Office 是微软发布的非常流行的办公 ...