2019 ICPC Asia Jakarta Regional Contest K. Addition Robot (线段树+矩阵乘法)
题意:
有一个长度为N的字符串,只含有AB两种字符,接下来有2种操作
1.l r 将区间[l, r]内的A变成B,B变成A
2.l r a b 在区间[l, r]内,如果遇到A,a变成a和b之和,反之,b变成a和b之和,并输出最终的a b
思路:
对于操作二:
遇到A其实就相当于(a,b) * (1 0 1 1)
遇到B其实就相当于(a,b) * (1 1 0 1)
操作一:
对当前答案矩阵“转置”,swap(a[0][0],a[1][1]),swap(a[1][0],a[1][0])???
#include<bits/stdc++.h>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e5+5;
int n,m,lazy[maxn<<2];
char s[maxn];
struct node{
ll a[2][2];
node operator * (const node& x){
node t;
memset(t.a,0,sizeof(t.a));
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
t.a[i][j]=(t.a[i][j]+a[i][k]*x.a[k][j]%mod)%mod;
return t;
}
}e[maxn<<2];
void pushdown(int rt,int l,int r){
if(lazy[rt]){
swap(e[rt<<1].a[0][1],e[rt<<1].a[1][0]);
swap(e[rt<<1].a[0][0],e[rt<<1].a[1][1]);
swap(e[rt<<1|1].a[0][1],e[rt<<1|1].a[1][0]);
swap(e[rt<<1|1].a[0][0],e[rt<<1|1].a[1][1]);
lazy[rt<<1]^=1;
lazy[rt<<1|1]^=1;
lazy[rt]=0;
}
}
void build(int rt,int l,int r){
if(l==r){
if(s[l]=='A'){
e[rt].a[0][0]=1;
e[rt].a[0][1]=0;
e[rt].a[1][0]=1;
e[rt].a[1][1]=1;
}
else{
e[rt].a[0][0]=1;
e[rt].a[0][1]=1;
e[rt].a[1][0]=0;
e[rt].a[1][1]=1;
}
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
e[rt]=e[rt<<1]*e[rt<<1|1];
}
void update(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y){
swap(e[rt].a[0][1],e[rt].a[1][0]);
swap(e[rt].a[0][0],e[rt].a[1][1]);
lazy[rt]^=1;
return;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if(x<=mid)update(lson,x,y);
if(y>mid)update(rson,x,y);
e[rt]=e[rt<<1]*e[rt<<1|1];
}
node query(int rt,int l,int r,int x,int y){
if(x<=l&r<=y){
return e[rt];
}
int mid=(l+r)>>1;
node ans;
ans.a[0][0]=1;
ans.a[0][1]=0;
ans.a[1][0]=0;
ans.a[1][1]=1;
pushdown(rt,l,r);
if(x<=mid)ans=ans*query(lson,x,y);
if(y>mid)ans=ans*query(rson,x,y);
return ans;
}
int main(){
scanf("%d%d%s",&n,&m,s+1);
build(1,1,n);
while(m--){
int op,x,y,a,b;
scanf("%d",&op);
if(op==1){
scanf("%d%d",&x,&y);
update(1,1,n,x,y);
}
else {
scanf("%d%d%d%d",&x,&y,&a,&b);
node ans=query(1,1,n,x,y),t;
t.a[0][0]=a,t.a[0][1]=b;
t.a[1][0]=0,t.a[1][1]=0;
ans=t*ans;
printf("%lld %lld\n",ans.a[0][0],ans.a[0][1]);
}
}
}