2019-2020 ICPC, Asia Jakarta Regional Contest K. Addition Robot(線段樹 + 矩陣乘法)

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Adding two numbers several times is a time-consuming task, so you want to build a robot. The robot should have a string S=S1S2…SNS=S1S2…SN of NN characters on its memory that represents addition instructions. Each character of the string, SiSi, is either 'A' or 'B'.

You want to be able to give QQ commands to the robot, each command is either of the following types:

  • 1 LL RR. The robot should toggle all the characters of SiSi where L≤i≤RL≤i≤R. Toggling a character means changing it to 'A' if it was previously 'B', or changing it to 'B' if it was previously 'A'.
  • 2 LL RR AA BB. The robot should call f(L,R,A,B)f(L,R,A,B) and return two integers as defined in the following pseudocode:
        function f(L, R, A, B):
          FOR i from L to R
            if S[i] = 'A'
              A = A + B
            else
              B = A + B
          return (A, B)
      

You want to implement the robot's expected behavior.

Input

Input begins with a line containing two integers: NN QQ (1≤N,Q≤1000001≤N,Q≤100000) representing the number of characters in the robot's memory and the number of commands, respectively. The next line contains a string SS containing NN characters (each either 'A' or 'B') representing the initial string in the robot's memory. The next QQ lines each contains a command of the following types.

  • 1 LL RR (1≤L≤R≤N1≤L≤R≤N)
  • 2 LL RR AA BB (1≤L≤R≤N1≤L≤R≤N; 0≤A,B≤1090≤A,B≤109)

There is at least one command of the second type.

Output

For each command of the second type in the same order as input, output in a line two integers (separated by a single space), the value of AA and BB returned by f(L,R,A,B)f(L,R,A,B), respectively. As this output can be large, you need to modulo the output by 10000000071000000007.

Example

input

Copy

5 3
ABAAA
2 1 5 1 1
1 3 5
2 2 5 0 1000000000

output

Copy

11 3
0 1000000000

Note

Explanation for the sample input/output #1

For the first command, calling f(L,R,A,B)f(L,R,A,B) causes the following:

  • Initially, A=1A=1 and B=1B=1.
  • At the end of i=1i=1, A=2A=2 and B=1B=1.
  • At the end of i=2i=2, A=2A=2 and B=3B=3.
  • At the end of i=3i=3, A=5A=5 and B=3B=3.
  • At the end of i=4i=4, A=8A=8 and B=3B=3.
  • At the end of i=5i=5, A=11A=11 and B=3B=3.

Therefore, f(L,R,A,B)f(L,R,A,B) will return (11,3)(11,3).

For the second command, string SS will be updated to "ABBBB".

For the third command, the value of AA will always be 00 and the value of BB will always be 10000000001000000000. Therefore, f(L,R,A,B)f(L,R,A,B) will return (0,1000000000)(0,1000000000).

題意:

有一個長度爲n的只含‘A’ ‘B’的字符串。

兩種操作, 1號操作, 將一個區間的內的A與B互換

2號操作詢問區間內的值, 給出起始A, B

在該區間內遇到字符A, A = A + B,遇到字符B, B = B + A

問最後A, B的值爲多少?

思路:

對於查詢操作, 我們可以線段樹套個矩陣乘法, 就可以得出答案了

對於修改操作, 我們在線段樹內每個節點存兩種矩陣,然後遇到修改時

交換兩種矩陣即可。

\begin{bmatrix} A & B \end{bmatrix} * \begin{bmatrix} 1 &0 \\1 & 1 \end{bmatrix} = \begin{bmatrix} A + B & B \end{bmatrix}

\begin{bmatrix} A & B \end{bmatrix} * \begin{bmatrix} 1 &1 \\0 & 1 \end{bmatrix} = \begin{bmatrix} A & B + A \end{bmatrix}

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
const int mod = 1e9 + 7;
const int N = 2e5 + 100;
struct M
{
	ll m[2][2];
	M()
	{
		memset(m, 0, sizeof m);
	}
}A, B;
M c[N * 4][2];
int lzy[N * 4];
char s[N];
M mul(M a, M b)
{
	M ans;
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 2; j++)
			for (int k = 0; k < 2; k++)
				ans.m[i][j] = (ans.m[i][j] + a.m[i][k] * b.m[k][j] % mod) % mod;
	return ans;
}
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
#define mid  ((L) + (R) >> 1)
void push_up(int x)
{
	c[x][0] = mul(c[ls][0], c[rs][0]);
	c[x][1] = mul(c[ls][1], c[rs][1]);
}
void pushDown(int x)
{
	if (lzy[x])
	{
		swap(c[ls][0], c[ls][1]);
		swap(c[rs][0], c[rs][1]);
		lzy[ls] ^= 1;
		lzy[rs] ^= 1;
		lzy[x] = 0;
	}
}
void build(int x, int L, int R)
{
	if (L == R)
	{
		if (s[L] == 'A')
			c[x][0] = A, c[x][1] = B;
		else
			c[x][0] = B, c[x][1] = A;
		return;
	}
	build(ls, L, mid);
	build(rs, mid + 1, R);
	push_up(x);
}
void update(int x, int L, int R, int ql, int qr)
{
	if (ql <= L && qr >= R)
	{
		swap(c[x][0], c[x][1]);
		lzy[x] ^= 1;
		return;
	}
	pushDown(x);
	if (ql <= mid)
		update(ls, L, mid, ql, qr);
	if (qr > mid)
		update(rs, mid + 1, R, ql, qr);
	push_up(x);
}
void query(int x, int L, int R, int ql, int qr, M& ans)
{
	if (ql <= L && qr >= R)
	{
		ans = mul(ans, c[x][0]);
		return;
	}
	pushDown(x);
	if (ql <= mid)
		query(ls, L, mid, ql, qr, ans);
	if (qr > mid)
		query(rs, mid + 1, R, ql, qr, ans);
	push_up(x);
}
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	A.m[0][0] = A.m[1][0] = A.m[1][1] = B.m[0][0] = B.m[0][1] = B.m[1][1] = 1;
	int n, q;
	scanf("%d%d", &n, &q);
	scanf("%s", s + 1);
	build(1, 1, n);
	while (q--)
	{
		int op;
		cin >> op;
		if (op == 1)
		{
			int L, R;
			scanf("%d%d", &L, &R);
			update(1, 1, n, L, R);
		}
		else
		{
			int L, R, A, B;
			scanf("%d%d%d%d", &L, &R, &A, &B);
			M base, ans;
			ans.m[0][0] = ans.m[1][1] = 1;
			base.m[0][0] = A; base.m[0][1] = B;
			query(1, 1, n, L, R, ans);
			base = mul(base, ans);
			printf("%lld %lld\n", base.m[0][0], base.m[0][1]);
		}
	}
	return TIME;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章