K - Addition Robot CodeForces - 1252K

题解:对于线段树上的一段,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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值