HDU6155 Subsequence Count

Subsequence Count

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Others)
Total Submission(s): 933 Accepted Submission(s): 329

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

Source

2017中国大学生程序设计竞赛 - 网络选拔赛

题解

看到此题直接想怎么用数据结构维护。。。就GG了。。
发现可以DP,看看能不能矩阵快速幂,然后拿数据结构维护矩阵乘法
dp[i][0]表示从开始(标记为1)到i,以0位结尾的本质不同的子序列个数
dp[i][1]表示从开始(标记为1)到i,以1位结尾的本质不同的子序列个数
如果numi = 0 dp[i][0] = dp[i - 1][1] + dp[i - 1][0] + 1, dp[i][1] = dp[i - 1][1]
矩阵
dp[i][0] dp[i][1] 1

1 0 0
1 1 0
1 0 1
如果numi = 1 dp[i][0] = dp[i - 1][0], dp[i][1] = dp[i - 1][0] + dp[i - 1][1] + 1
矩阵
dp[i][0] dp[i][1] 1

1 1 0
0 1 0
0 1 1

矩阵乘法有结合律,拿线段树维护矩阵乘法就好了。
还可以用线段树维护0/1个数,倍增求答案矩阵(矩阵ksm)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(x) ((x) < 0 ? -1 * (x) : (x))
template <class T>
inline void swap(T &x, T &y)
{
	T tmp = x;x = y, y = tmp;
} 

template <class T>
inline void read(T &x)
{
	x = 0;char ch = getchar(), c = ch;
	while(ch < '0' || ch > '9') c = ch, ch = getchar();
	while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
	if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAXN = 200000 + 10;

struct Matrix
{
	long long data[3][3];
	Matrix(){memset(data, 0, sizeof(data));}
	friend Matrix operator*(const Matrix &a, const Matrix &b)
	{
		Matrix ans;
		for(int k = 0;k < 3;++ k)
			for(int i = 0;i < 3;++ i)
				for(int j = 0;j < 3;++ j)
					ans.data[i][j] += a.data[i][k] * b.data[k][j], ans.data[i][j] %= MOD;
		return ans;
	}
};
struct Node
{
	int l, r, lazy;
	Matrix data;
	Node(){l = r = -1, lazy = 0;}
}node[MAXN << 2];
inline void change(Node &x)
{
	swap(x.data.data[0][0], x.data.data[1][1]);
	swap(x.data.data[0][1], x.data.data[1][0]);
	swap(x.data.data[0][2], x.data.data[1][2]);
	swap(x.data.data[2][0], x.data.data[2][1]);
}
void pushdown(int &o)
{
	if(!node[o].lazy) return;
	node[o].lazy = 0;
	change(node[o << 1]), node[o << 1].lazy ^= 1;
	change(node[o << 1 | 1]), node[o << 1 | 1].lazy ^= 1;
}
Node merge(Node &a, Node &b)
{
	if(a.l == -1) return b;
	if(b.l == -1) return a;
	Node re;
	re.l = a.l, re.r = b.r;
	re.data = a.data * b.data;
	return re;
}

int num[MAXN], t, n, q;
char s[MAXN];
Matrix dp0, dp1;

void build(int o = 1, int l = 1, int r = n)
{
	if(l == r)
	{
		node[o].l = l, node[o].r = r, node[o].lazy = 0;
		if(num[l]) node[o].data = dp1;
		else node[o].data = dp0;
		return;
	}
	int mid = (l + r) >> 1;
	build(o << 1, l, mid);
	build(o << 1 | 1, mid + 1, r);
	node[o] = merge(node[o << 1], node[o << 1 | 1]);
	return;
}
void modify(int ll, int rr, int o = 1)
{
	pushdown(o);
	if(ll <= node[o].l && rr >= node[o].r)
	{
		change(node[o]), node[o].lazy ^= 1;
		return;
	}
	int mid = (node[o].l + node[o].r) >> 1;
	if(mid >= ll) modify(ll, rr, o << 1);
	if(mid < rr) modify(ll, rr, o << 1 | 1);
	node[o] = merge(node[o << 1], node[o << 1 | 1]);
	return;
} 
Node ask(int ll, int rr, int o = 1)
{
	pushdown(o);
	if(ll <= node[o].l && rr >= node[o].r) return node[o];
	int mid = (node[o].l + node[o].r) >> 1;
	Node a,b;
	if(mid >= ll) a = ask(ll, rr, o << 1);
	if(mid < rr) b = ask(ll, rr, o << 1 | 1);
	Node re = merge(a, b);
	return re;
}

int main()
{
	read(t);
	dp0.data[0][0] = dp0.data[1][0] = dp0.data[1][1] = dp0.data[2][0] = dp0.data[2][2] = 1;
	dp1.data[0][0] = dp1.data[0][1] = dp1.data[1][1] = dp1.data[2][1] = dp1.data[2][2] = 1;
	for(;t;--t)
	{
		read(n), read(q);
		scanf("%s", s + 1);
		for(int i = 1;i <= n;++ i) num[i] = s[i] - '0';
		build();
		for(int i = 1;i <= q;++ i)
		{
			int tmp1,tmp2,tmp3;
			read(tmp1), read(tmp2), read(tmp3);
			if(tmp1 == 1) modify(tmp2, tmp3);
			else
			{
				Node tmp = ask(tmp2, tmp3);
				printf("%lld\n", (tmp.data.data[2][0] + tmp.data.data[2][1]) % MOD);
			}
		}
	}
	return 0;
}
posted @ 2018-02-22 14:50  嘒彼小星  阅读(453)  评论(0编辑  收藏  举报