Hdu 6155 线段树维护转移矩阵

这个题难点不在线段树上,事实上只要解决了如何求一个01串有多少个不同子串的问题之后,基本上就是一马平川了。所以我队因为不会计数比赛的时候GG了。。。之后围观了叉姐的题解学会了计数,就xjb写完了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=105000;

struct mat{
    ll a[3][3];
    void init(int tag){
        memset(a, 0, sizeof(a));
        if(tag==0){
            a[0][0]=a[0][1]=a[0][2]=a[1][1]=a[2][2]=1;
        }
        else {
            a[0][0]=a[1][0]=a[1][1]=a[1][2]=a[2][2]=1;
        }
    }
    void rev(){
        swap(a[0][0], a[1][1]);
        swap(a[0][1], a[1][0]);
        swap(a[0][2], a[1][2]);
    }
};

mat operator*(const mat& a, const mat& b){
    mat ans;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            ans.a[i][j]=0;
            for(int k=0;k<3;k++){
                ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
            }
        }
    }
    return ans;
}

char s[maxn];
int n, m;

mat rec[maxn<<2];
int lz[maxn<<2];

void pushdown(int u){
    if(!lz[u])return ;
    rec[2*u].rev();
    lz[2*u]^=1;
    rec[2*u+1].rev();
    lz[2*u+1]^=1;
    lz[u]=0;
}

void pushup(int u){
    rec[u]=rec[2*u+1]*rec[2*u];
}

void build(int u, int l, int r){
    lz[u]=0;
    if(l==r){
        rec[u].init(s[l]-'0');
        return ;
    }
    int mid=(l+r)>>1;
    build(2*u, l, mid);
    build(2*u+1, mid+1, r);
    pushup(u);
}

void update(int u, int ql, int qr, int l, int r){
    if(ql>r||qr<l)return;
    if(ql<=l&&r<=qr){
        rec[u].rev();
        lz[u]^=1;
        return ;
    }
    int mid=(l+r)>>1;
    pushdown(u);
    update(2*u, ql, qr, l, mid);
    update(2*u+1, ql, qr, mid+1, r);
    pushup(u);
}

mat query(int u, int ql, int qr, int l, int r){
    if(ql<=l&&r<=qr){
        return rec[u];
    }
    int mid=(l+r)>>1;
    pushdown(u);
    mat ret;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++)ret.a[i][j]=(i==j);
    }
    if(mid>=ql)ret=query(2*u, ql, qr, l, mid)*ret;
    if(mid+1<=qr)ret=query(2*u+1, ql, qr, mid+1, r)*ret;
    return ret;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        scanf("%s", s+1);
        build(1, 1, n);
        for(int i=1;i<=m;i++){
            int tag, l, r;
            scanf("%d%d%d", &tag, &l, &r);
            if(tag==1){
                update(1, l, r, 1, n);
            }
            else {
                mat m=query(1, l, r, 1, n);
                printf("%lld\n", (m.a[0][2]+m.a[1][2])%mod);
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/mrbird_to_fly/article/details/77428903
今日推荐