題目大意
給你一個串 包含AB兩種元素,進行以下兩種操作
1、給定一個區間 將 A 變成 B,B 變成 A
2、給定一個查詢區間 以及 兩個數 x,y
在區間 中如果 那麼 x = x+y
否則 y=x+y
查詢這個區間最後的x,y分別是多少
題目分析
剛拿到這個題有些無從分析
我們考慮
x=x+y 、 y=x+y
這兩個操作,發現可以寫成矩陣的形式
所以,我們考慮線段樹維護區間矩陣乘積
那麼當我們在進行修改的時候,對於一個區間而言,其實乘積只有可能有兩種。所以每個點維護這兩種乘積即可。
如果修改區間的話,就交換這兩種乘積。然後修改父親結點即可。
代碼詳解
#include <bits/stdc++.h>
using namespace std;
const int maxn =4e5+50;
const int mod = 1e9+7;
typedef long long ll;
string s;
struct Mat
{
int a[2][2];
};
Mat A,B,E;
Mat mul(Mat x,Mat y)
{
Mat t;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
{
t.a[i][j]=0;
for(int k=0;k<2;k++)
t.a[i][j] += ((ll)x.a[i][k] * (ll)y.a[k][j])%mod;
t.a[i][j] %=mod;
}
return t;
}
struct Node
{
int l,r;
Mat w[2];
int flag = 0;
}node[maxn];
void pt(int root)
{
cout<<root<<endl;
cout<<node[root].l<<" "<<node[root].r<<endl;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
cout<<node[root].w[0].a[i][j]<<" ";
}
cout<<endl;
}
}
void pushup(int root)
{
node[root].w[0] =mul(node[root*2].w[0],node[root*2+1].w[0]);
node[root].w[1] =mul(node[root*2].w[1],node[root*2+1].w[1]);
}
void pushdown(int root)
{
if(node[root].flag)
{
node[root*2].flag^=1;
swap(node[root*2].w[0],node[root*2].w[1]);
node[root*2+1].flag^=1;
swap(node[root*2+1].w[0],node[root*2+1].w[1]);
node[root].flag^=1;
}
}
void build(int root,int l,int r)
{
if(l>r) return ;
node[root].l = l;
node[root].r = r;
node[root].flag=0;
if(l==r)
{
if(s[l-1]=='A')
node[root].w[0] =A,node[root].w[1] = B;
else node[root].w[0]=B,node[root].w[1] =A;
//pt(root);
return;
}
int mid = (l+r)/2;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
pushup(root);
//pt(root);
}
void update(int root,int st,int ed)
{
int l = node[root].l;
int r = node[root].r;
//cout<<st<<" "<<ed<<" "<<l<<" "<<r<<endl;
if(st>r||ed<l) return;
if(st<=l&&ed>=r)
{
node[root].flag^=1;
swap(node[root].w[0],node[root].w[1]);
//pt(root);
return;
}
pushdown(root);
update(root*2,st,ed);
update(root*2+1,st,ed);
pushup(root);
//pt(root);
}
Mat query(int root,int st,int ed)
{
int l = node[root].l;
int r = node[root].r;
if(l>ed||r<st) return E;
if(st<=l&&ed>=r)
{
return node[root].w[0];
}
Mat x=E;
pushdown(root);
x=mul(x,query(root*2,st,ed));
x=mul(x,query(root*2+1,st,ed));
pushup(root);
return x;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
cin>>s;
A.a[0][0] = 1; A.a[0][1] = 0; A.a[1][0] = 1; A.a[1][1] = 1;
B.a[0][0] = 1; B.a[0][1] = 1; B.a[1][0] = 0; B.a[1][1] = 1;
E.a[0][0] = 1; E.a[0][1] = 0; E.a[1][0] = 0; E.a[1][1] = 1;
build(1,1,n);
for(int i=1;i<=q;i++)
{
int op;
scanf("%d",&op);
if(op==1)
{
int l,r;
scanf("%d%d",&l,&r);
update(1,l,r);
}
if(op==2)
{
int l,r,x,y;
scanf("%d%d%d%d",&l,&r,&x,&y);
Mat t = query(1,l,r);
ll le =((ll)t.a[0][0]*(ll)x%mod+(ll)t.a[1][0]*(ll)y%mod)%mod;
ll ri = ((ll)t.a[0][1]*(ll)x%mod+ (ll) t.a[1][1]*(ll)y%mod)%mod;
printf("%I64d %I64d\n",le,ri);
}
}
return 0;
}