题解:对于线段树上的一段,Ax=x*a1+y*b1 , Bx=x*a2+y*b2, x,y为初始给的A,B值,Ax,Bx,为操作完这一段的结果值,如果线段树上两段合并前一段的Ax为后一段的x,前一段的Bx为后一段的y,带入结果就算出两段合并的值。对于反转操作,其实就是Ax变为 Bx,然后a和b交换。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1000000007;
const int maxn=1e5+5;
struct node{
ll a1,b1;
ll a2,b2;
}tree[maxn*4]; int laz[maxn*4];
char str[maxn];
void push_up(int x){
if(laz[x]==0) return ;
int ls=x<<1,rs=x<<1|1;
swap(tree[ls].a1,tree[ls].a2);
swap(tree[ls].b1,tree[ls].b2);
swap(tree[ls].a1,tree[ls].b1);
swap(tree[ls].a2,tree[ls].b2);
swap(tree[rs].a1,tree[rs].a2);
swap(tree[rs].b1,tree[rs].b2);
swap(tree[rs].a1,tree[rs].b1);
swap(tree[rs].a2,tree[rs].b2);
laz[ls]^=laz[x]; laz[rs]^=laz[x];
laz[x]=0;
}
void push_down(int x){
int ls=x<<1,rs=x<<1|1;
tree[x].a1=tree[rs].a1*tree[ls].a1+tree[rs].b1*tree[ls].a2;
tree[x].b1=tree[rs].a1*tree[ls].b1+tree[rs].b1*tree[ls].b2;
tree[x].a2=tree[rs].a2*tree[ls].a1+tree[rs].b2*tree[ls].a2;
tree[x].b2=tree[rs].a2*tree[ls].b1+tree[rs].b2*tree[ls].b2;
tree[x].a1%=mod; tree[x].a2%=mod; tree[x].b1%=mod; tree[x].b2%=mod;
}
void build(int x,int l,int r){
tree[x].a1=tree[x].b2=1;tree[x].a2=tree[x].b1=0;
laz[x]=0;
if(l==r){
if(str[l]=='A') tree[x].b1++;
else tree[x].a2++;
return ;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_down(x);
}
void add(int x,int l,int r,int lx,int rx){
if(l==lx&&r==rx){
laz[x]^=1;
swap(tree[x].a1,tree[x].a2);
swap(tree[x].b1,tree[x].b2);
swap(tree[x].a1,tree[x].b1);
swap(tree[x].a2,tree[x].b2);
return ;
}
int mid=(l+r)>>1;
push_up(x);
if(rx<=mid) add(x<<1,l,mid,lx,rx);
else if(lx>mid) add(x<<1|1,mid+1,r,lx,rx);
else add(x<<1,l,mid,lx,mid),add(x<<1|1,mid+1,r,mid+1,rx);
push_down(x);
}
node query(int x,int l,int r,int lx,int rx){
if(l==lx&&r==rx){
return tree[x];
}
push_up(x);
int mid=(l+r)>>1;
node p;
if(rx<=mid) p=query(x<<1,l,mid,lx,rx);
else if(lx>mid) p=query(x<<1|1,mid+1,r,lx,rx);
else {
node ls=query(x<<1,l,mid,lx,mid);
node rs=query(x<<1|1,mid+1,r,mid+1,rx);
p.a1=rs.a1*ls.a1+rs.b1*ls.a2;
p.b1=rs.a1*ls.b1+rs.b1*ls.b2;
p.a2=rs.a2*ls.a1+rs.b2*ls.a2;
p.b2=rs.a2*ls.b1+rs.b2*ls.b2;
p.a1%=mod; p.a2%=mod; p.b1%=mod; p.b2%=mod;
}
push_down(x);
return p;
}
//void dfs(int x,int l,int r){
// if(l==r) {
// cout<<tree[x].a1<<' '<<tree[x].b1<<' '<<tree[x].a2<<' '<<tree[x].b2<<endl;
// return ;
// }
// int mid=(l+r)>>1;
// dfs(x<<1,l,mid);
// dfs(x<<1|1,mid+1,r);
//}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
scanf("%s",str+1);
build(1,1,n);
// node Q=query(1,1,n,3,5);
// cout<<Q.a1<<' '<<Q.b1<<' '<<Q.a2<<' '<<Q.b2<<endl;
// dfs(1,1,n);
while(m--){
int op,a,b;
ll c,d;
scanf("%d",&op);
if(op==1){
scanf("%d %d",&a,&b);
add(1,1,n,a,b);
}else {
scanf("%d %d %lld %lld",&a,&b,&c,&d);
node Q=query(1,1,n,a,b);
// cout<<Q.a1<<' '<<Q.b1<<' '<<Q.a2<<' '<<Q.b2<<endl;
ll ax=Q.a1*c+Q.b1*d;
ll bx=Q.a2*c+Q.b2*d;
ax%=mod; bx%=mod;
printf("%lld %lld\n",ax,bx);
}
}
return 0;
}