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].
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
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+20,M=1e6+10,inf=2147483647; inline LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const LL mod = 1e9+7; char s[N]; struct Matix { LL arr[3][3]; }E,F,again,EE; inline Matix mul(Matix a,Matix b) { Matix ans; memset(ans.arr,0,sizeof(ans.arr)); for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { for(int k = 0; k < 3; k++) ans.arr[i][j] += a.arr[i][k] * b.arr[k][j],ans.arr[i][j] %= mod; } } return ans; } Matix v[N * 4],now,facE[N],facF[N]; int lazy[N * 4],fi[N * 4],se[N * 4]; void change(int i) { swap(v[i].arr[0][0],v[i].arr[1][0]); swap(v[i].arr[0][1],v[i].arr[1][1]); swap(v[i].arr[0][2],v[i].arr[1][2]); swap(v[i].arr[0][0],v[i].arr[0][1]); swap(v[i].arr[1][0],v[i].arr[1][1]); swap(v[i].arr[2][0],v[i].arr[2][1]); } void push_down(int i,int ll,int rr) { if(!lazy[i]) return; lazy[ls] ^= 1; lazy[rs] ^= 1; change(ls);change(rs); lazy[i] ^= 1; } 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] = 0; if(ll == rr) { if(s[ll] == '1') v[i] = E,fi[i] = 1,se[i] = 0; else v[i] = F,fi[i] = 0,se[i] = 1; return ; } build(ls,ll,mid); build(rs,mid+1,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] ^= 1; change(i); return ; } if(y <= mid) update(ls,ll,mid,x,y); else if(x > mid) update(rs,mid+1,rr,x,y); else update(ls,ll,mid,x,mid),update(rs,mid+1,rr,mid+1,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+1,rr,x,y); else return mul(ask(ls,ll,mid,x,mid),ask(rs,mid+1,rr,mid+1,y)); push_up(i,ll,rr); } int main() { EE.arr[0][0] = 1,EE.arr[1][1] = 1,EE.arr[2][2] = 1; E.arr[0][0] = 1;E.arr[0][1] = 1;E.arr[0][2] = 1; E.arr[1][1] = 1;E.arr[2][2] = 1; F.arr[0][0] = 1;F.arr[1][0] = 1;F.arr[1][1] = 1; F.arr[1][2] = 1;F.arr[2][2] = 1; again.arr[0][2] = 1; int T; T = read(); while(T--) { int n,Q; n = read(); Q = read(); scanf("%s",s+1); build(1,1,n); while(Q--) { int op,l,r; op = read(); l = read(); r = read(); if(op == 1) update(1,1,n,l,r); else { now = mul(again,ask(1,1,n,l,r)); printf("%lld ",(now.arr[0][0]+now.arr[0][1])%mod); } } } return 0; }
先考虑怎么算 s1,s2,…,sn
的答案。设 dp(i,0/1)
表示考虑到 si
,以 0/1
结尾的串的数量。那么 dp(i,0)=dp(i−1,0)+dp(i−1,1)+1
. 1
也同理。
那么假设在某个区间之前,dp(i,0/1)=(x,y)
的话,过了这段区间,就会变成 (ax+by+c,dx+ey+f)
的形式,只要用线段树维护这个线性变化就好了。