题目大意
给你一个串 包含AB两种元素,进行以下两种操作
1、给定一个区间[l,r][l,r][l,r] 将 A 变成 B,B 变成 A
2、给定一个查询区间 [l,r][l,r][l,r] 以及 两个数 x,y
在区间 [l,r][l,r][l,r]中如果 s[i]=As[i] =As[i]=A 那么 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;
}


被折叠的 条评论
为什么被折叠?



