Subsequence Count

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others)

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

There are two types of queries:

1. Flipping the bits (i.e., changing all 1 to 0 and 0 to 1) between l and r (inclusive).
2. Counting the number of distinct subsequences in the substring S[l,...,r].

 
Input
The first line contains an integer T, denoting the number of the test cases.

For each test, the first line contains two integers N and Q.

The second line contains the string S.

Then Q lines follow, each with three integers type, l and r, denoting the queries.

1≤T≤5

1≤N,Q≤105

S[i]∈{0,1},∀1≤i≤N

type∈{1,2}

1≤l≤r≤N

 
Output
For each query of type 2, output the answer mod (109+7) in one line.
 
Sample Input
2
4 4
1010
2 1 4
2 2 4
1 2 3
2 1 4
4 4
0000
1 1 2
1 2 3
1 3 4
2 1 4
 
Sample Output
11
6
8
10
 
题解:
  设定dp[i][0/1] 到第i个字符以0/1结尾的子序列方案
  若s[i] = =1 : dp[i][1] = dp[i-1][0] + dp[i-1][1] + 1;
        dp[i][0] = dp[i-1][0];
       若是s[i] == 0: dp[i][0] =  dp[i-1][0] + dp[i-1][1] + 1;
        dp[i][1] = dp[i-1][1];
  写成矩阵,用线段树维护一段连续矩阵乘积,有点卡常数
#include<bits/stdc++.h>
using namespace std;
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
typedef unsigned long long ULL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N=5e5+,M=1e6+,inf=; inline LL read(){
LL x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} const LL mod = 1e9+;
char s[N]; struct Matix {
LL arr[][];
}E,F,again,EE;
inline Matix mul(Matix a,Matix b) {
Matix ans;
memset(ans.arr,,sizeof(ans.arr));
for(int i = ; i < ; i++) {
for(int j = ; j < ; j++) {
for(int k = ; k < ; k++)
ans.arr[i][j] += a.arr[i][k] * b.arr[k][j],ans.arr[i][j] %= mod;
}
}
return ans;
} Matix v[N * ],now,facE[N],facF[N];
int lazy[N * ],fi[N * ],se[N * ]; void change(int i) {
swap(v[i].arr[][],v[i].arr[][]);
swap(v[i].arr[][],v[i].arr[][]);
swap(v[i].arr[][],v[i].arr[][]);
swap(v[i].arr[][],v[i].arr[][]);
swap(v[i].arr[][],v[i].arr[][]);
swap(v[i].arr[][],v[i].arr[][]);
}
void push_down(int i,int ll,int rr) {
if(!lazy[i]) return;
lazy[ls] ^= ;
lazy[rs] ^= ;
change(ls);change(rs);
lazy[i] ^= ;
}
inline void push_up(int i,int ll,int rr) {
v[i] = mul(v[ls],v[rs]);
}
void build(int i,int ll,int rr) {
lazy[i] = ;
if(ll == rr) {
if(s[ll] == '') v[i] = E,fi[i] = ,se[i] = ;
else v[i] = F,fi[i] = ,se[i] = ;
return ;
}
build(ls,ll,mid);
build(rs,mid+,rr);
push_up(i,ll,rr);
}
inline void update(int i,int ll,int rr,int x,int y) {
push_down(i,ll,rr);
if(ll == x && rr == y) {
lazy[i] ^= ;
change(i);
return ;
}
if(y <= mid) update(ls,ll,mid,x,y);
else if(x > mid) update(rs,mid+,rr,x,y);
else update(ls,ll,mid,x,mid),update(rs,mid+,rr,mid+,y);
push_up(i,ll,rr);
}
inline Matix ask(int i,int ll,int rr,int x,int y) {
push_down(i,ll,rr);
if(ll == x && rr == y) {
return v[i];
}
if(y <= mid) return ask(ls,ll,mid,x,y);
else if(x > mid) return ask(rs,mid+,rr,x,y);
else return mul(ask(ls,ll,mid,x,mid),ask(rs,mid+,rr,mid+,y));
push_up(i,ll,rr);
} int main() {
EE.arr[][] = ,EE.arr[][] = ,EE.arr[][] = ; E.arr[][] = ;E.arr[][] = ;E.arr[][] = ;
E.arr[][] = ;E.arr[][] = ; F.arr[][] = ;F.arr[][] = ;F.arr[][] = ;
F.arr[][] = ;F.arr[][] = ; again.arr[][] = ; int T;
T = read();
while(T--) {
int n,Q;
n = read();
Q = read();
scanf("%s",s+);
build(,,n);
while(Q--) {
int op,l,r;
op = read();
l = read();
r = read();
if(op == )
update(,,n,l,r);
else {
now = mul(again,ask(,,n,l,r));
printf("%lld\n",(now.arr[][]+now.arr[][])%mod);
}
}
}
return ;
}
 

先考虑怎么算 s_1, s_2, \ldots, s_ns​1​​,s​2​​,…,s​n​​ 的答案。设 dp(i, 0/1)dp(i,0/1) 表示考虑到 s_is​i​​,以 0/10/1 结尾的串的数量。那么 dp(i, 0) =dp(i - 1, 0) + dp(i - 1, 1) + 1dp(i,0)=dp(i−1,0)+dp(i−1,1)+111 也同理。
那么假设在某个区间之前,dp(i, 0/1) = (x, y)dp(i,0/1)=(x,y) 的话,过了这段区间,就会变成 (ax + by + c, dx + ey + f)(ax+by+c,dx+ey+f) 的形式,只要用线段树维护这个线性变化就好了。

HDU 6155 Subsequence Count 线段树维护矩阵的更多相关文章

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

  2. Codeforces 750E - New Year and Old Subsequence(线段树维护矩阵乘法,板子题)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 我做这道 *2600 的动力是 wjz 出了道这个套路的题,而我连起码的思路都没有,wtcl/kk 首先考虑怎样对某个固定的串计 ...

  3. 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 ...

  4. hdu 5068 线段树维护矩阵乘积

    http://acm.hdu.edu.cn/showproblem.php?pid=5068 题意给的略不清晰 m个询问:从i层去j层的方法数(求连段乘积)或者修改从x层y门和x+1层z门的状态反转( ...

  5. 线段树维护矩阵【CF718C】 Sasha and Array

    Description 有一个长为\(n\)的数列\(a_{1},a_{2}...a_{n}\),你需要对这个数列维护如下两种操作: \(1\space l \space r\space x\) 表示 ...

  6. CF718C Sasha and Array(线段树维护矩阵)

    题解 (不会矩阵加速的先去学矩阵加速) 反正我想不到线段树维护矩阵.我太菜了. 我们在线段树上维护一个区间的斐波那契的列矩阵的和. 然后询问时提取每个符合题意列矩阵的答案项(不是列矩阵存了两项吗,一个 ...

  7. Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)

    Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...

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

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

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

随机推荐

  1. 九度oj 题目1340:小A的计算器

    题目描述: 以往的操作系统内部的数据表示都是二进制方式,小A新写了一个操作系统,系统内部的数据表示为26进制,其中0-25分别由a-z表示. 现在小A要在这个操作系统上实现一个计算器,这个计算器要能实 ...

  2. input加border-raduis之后再加border有阴影

    在border之前加入: background:no-repeat 0 0 scroll #fff;border:none;outline:medium;即可解决

  3. [luoguP2495] [SDOI2011]消耗战(DP + 虚树)

    传送门 明显虚树. 别的题解里都是这样说的. 先不考虑虚树,假设只有一组询问,该如何dp? f[u]表示把子树u中所有的有资源的节点都切掉的最优解 如果节点u需要切掉了话,$f[u]=val[u]$ ...

  4. 浅谈中途相遇攻击--meet-in-the-middle attack

    貌似挖的坑也够多了....好多都没填,这篇最后会不会TJ还得看心情TUT 看过大白书的人应该都会发现一种神奇的算法:中途相遇法.(在第58页)这种算法将以空间换时间的思路运用到了极致,但事实上它在密码 ...

  5. Oracle Partition 分区详细总结

    此文从以下几个方面来整理关于分区表的概念及操作:        1.表空间及分区表的概念        2.表分区的具体作用        3.表分区的优缺点        4.表分区的几种类型及操作 ...

  6. 集合-Vector

    Vector中的操作是线程安全的. public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCa ...

  7. 表单form-input标签禁止聚焦输入

    1.input标签禁止聚焦输入(针对小程序) <input type="text" disabled /> input标签禁止聚焦输入(针对网页html) 1).< ...

  8. windows symbol server调试

    linux下gdb强大的调试功能让人印象深刻,一直以为windows下调试可执行程序非常让人头痛.经一些高人指点后知道原来windows下还有symbol server这种调试工具 参见下面两个文档 ...

  9. 内核调试 SystemTap

    http://www.cnblogs.com/wangkangluo1/archive/2012/06/26/2562971.html   相关技术:utrace, probe, ftrace, dt ...

  10. 用canvas实现一个colorpicker

    http://www.cnblogs.com/ufex/p/6382982.html 每个浏览器都有自己的特点,比如今天要做的colorpicker就是,一千个浏览器,一千个哈姆雷特,一千个color ...