原题链接:https://codeforces.ml/problemset/problem/1252/K
有一个长度为N的字符串,只含有AB两种字符,接下来有2种操作
第一个操作区间翻转可以用线段树轻松维护,但第二个操作有些棘手。
学过矩阵乘法的同学都知道
遇到A其实就相当于(a,b) * (1 0 1 1)
遇到B其实就相当于(a,b) * (1 1 0 1)
这样处理的话我们可以在建线段树的时候就处理好矩阵
然后再看第一个操作,有两种方法
#include
using namespace std;
//#define ACM_LOCAL
#define re register
#define fi first
#define se second
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
struct Matrix {
ll a[2][2];
inline Matrix operator * (const Matrix& rhs) {
Matrix ret;
memset(&ret, 0, sizeof ret);
for (int i = 0; i <= 1; i++)
for (int j = 0; j <= 1; j++)
for (int k = 0; k <= 1; k++)
ret.a[i][j] = (ret.a[i][j] + a[i][k] * rhs.a[k][j] % MOD) % MOD;
return ret;
}
}mp;
struct Node {
int l, r;
int tag;
Matrix sum;
}t[N<<2];
string s;
void push_up(int u) {
t[u].sum = t[u<<1].sum * t[u<<1|1].sum;
}
void push_down(int u) {
if (t[u].tag) {
t[u<<1].tag ^= t[u].tag;
t[u<<1|1].tag ^= t[u].tag;
swap(t[u<<1].sum.a[0][0], t[u<<1].sum.a[1][1]);
swap(t[u<<1].sum.a[1][0], t[u<<1].sum.a[0][1]);
swap(t[u<<1|1].sum.a[0][0], t[u<<1|1].sum.a[1][1]);
swap(t[u<<1|1].sum.a[1][0], t[u<<1|1].sum.a[0][1]);
t[u].tag = 0;
}
}
void build(int u, int l, int r) {
t[u].l = l, t[u].r = r, t[u].tag = 0;
if (l == r) {
if (s[l-1] == 'A') {
t[u].sum.a[0][0] = 1;
t[u].sum.a[0][1] = 0;
t[u].sum.a[1][0] = 1;
t[u].sum.a[1][1] = 1;
} else {
t[u].sum.a[0][0] = 1;
t[u].sum.a[0][1] = 1;
t[u].sum.a[1][0] = 0;
t[u].sum.a[1][1] = 1;
}
return;
}
int mid = (l + r) >> 1;
build(u<<1, l, mid);
build(u<<1|1, mid+1, r);
push_up(u);
}
void modify(int u, int ql, int qr) {
if (ql <= t[u].l && qr >= t[u].r) {
swap(t[u].sum.a[0][0], t[u].sum.a[1][1]);
swap(t[u].sum.a[0][1], t[u].sum.a[1][0]);
t[u].tag ^= 1;
return;
}
push_down(u);
int mid = (t[u].l + t[u].r) >> 1;
if (ql <= mid) modify(u<<1, ql, qr);
if (qr > mid) modify(u<<1|1, ql, qr);
push_up(u);
}
Matrix query(int u, int ql, int qr) {
if (ql <= t[u].l && qr >= t[u].r) return t[u].sum;
int mid = (t[u].l + t[u].r) >> 1;
push_down(u);
Matrix ret;
ret.a[0][0] = 1;
ret.a[0][1] = 0;
ret.a[1][0] = 0;
ret.a[1][1] = 1;
if (ql <= mid) ret = ret * query(u<<1, ql, qr);
if (qr > mid) ret = ret * query(u<<1|1, ql, qr);
return ret;
}
void solve() {
int n, m; cin >> n >> m;
cin >> s;
build(1, 1, n);
for (int i = 1; i <= m; i++) {
int opt, x, y; cin >> opt >> x >> y;
if (opt == 1) modify(1, x, y);
else {
int a, b; cin >> a >> b;
Matrix ret = query(1, x, y), ans;
ans.a[0][0] = a;
ans.a[0][1] = b;
ans = ans * ret;
printf("%lld %lld\n", ans.a[0][0], ans.a[0][1]);
}
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
#include
using namespace std;
//#define ACM_LOCAL
#define re register
#define fi first
#define se second
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
struct Matrix {
ll a[2][2];
Matrix (){
memset(a, 0, sizeof a);}
inline Matrix operator * (const Matrix& rhs) {
Matrix ret;
memset(&ret, 0, sizeof ret);
for (int i = 0; i <= 1; i++)
for (int j = 0; j <= 1; j++)
for (int k = 0; k <= 1; k++)
ret.a[i][j] = (ret.a[i][j] + a[i][k] * rhs.a[k][j] % MOD) % MOD;
return ret;
}
}A, B;
void init() {
A.a[0][0] = A.a[1][0] = A.a[1][1] = 1;
B.a[0][0] = B.a[0][1] = B.a[1][1] = 1;
}
int tag[N<<2];
Matrix sum[N<<2][2];
string s;
void push_up(int u) {
sum[u][0] = sum[u<<1][0] * sum[u<<1|1][0];
sum[u][1] = sum[u<<1][1] * sum[u<<1|1][1];
}
void push_down(int u) {
if (tag[u]) {
tag[u<<1] ^= tag[u];
tag[u<<1|1] ^= tag[u];
swap(sum[u<<1][0], sum[u<<1][1]);
swap(sum[u<<1|1][0], sum[u<<1|1][1]);
tag[u] = 0;
}
}
void build(int u, int l, int r) {
tag[u] = 0;
if (l == r) {
if (s[l-1] == 'A') {
sum[u][0] = A;
sum[u][1] = B;
} else {
sum[u][0] = B;
sum[u][1] = A;
}
return;
}
int mid = (l + r) >> 1;
build(u<<1, l, mid);
build(u<<1|1, mid+1, r);
push_up(u);
}
void modify(int u, int ql, int qr, int l, int r) {
if (ql <= l && qr >= r) {
swap(sum[u][0], sum[u][1]);
tag[u] ^= 1;
return;
}
push_down(u);
int mid = (l + r) >> 1;
if (ql <= mid) modify(u<<1, ql, qr, l, mid);
if (qr > mid) modify(u<<1|1, ql, qr, mid+1, r);
push_up(u);
}
Matrix query(int u, int ql, int qr, int l, int r) {
if (ql <= l && qr >= r) return sum[u][0];
int mid = (l + r) >> 1;
push_down(u);
Matrix ret;
ret.a[0][0] = 1;
ret.a[0][1] = 0;
ret.a[1][0] = 0;
ret.a[1][1] = 1;
if (ql <= mid) ret = ret * query(u<<1, ql, qr, l, mid);
if (qr > mid) ret = ret * query(u<<1|1, ql, qr, mid+1, r);
return ret;
}
void solve() {
int n, m; cin >> n >> m;
cin >> s;
init();
build(1, 1, n);
for (int i = 1; i <= m; i++) {
int opt, x, y; cin >> opt >> x >> y;
if (opt == 1) modify(1, x, y, 1, n);
else {
int a, b; cin >> a >> b;
Matrix ret = query(1, x, y, 1, n), ans;
ans.a[0][0] = a;
ans.a[0][1] = b;
ans = ans * ret;
printf("%lld %lld\n", ans.a[0][0], ans.a[0][1]);
}
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}