hdu 6155

来源:互联网 发布:js定时器setinterval 编辑:程序博客网 时间:2024/06/05 11:10

题目链接:点击打开链接


题解思路:假设dp[i][1]为到i位置尾部是1个个数有几个,dp[i][0]也是如此,那么假设第i个位置放1,那么dp[i][1] = dp[i-1][1]+dp[i-1][0]+1,dp[i][0] = dp[i-1][0],如果第i个位置放0那么dp[i][0] = dp[i-1][1]+dp[i-1][0]+1,dp[i][1] = dp[i-1][1].我们不妨用矩阵来解决这个问题,那么放1的状态转移矩阵应该是

1 1 1    放0的是 1 0 0

0 1 0                   1 1 1

0 0 1,               0 0 1,这里也要注意线段树矩阵合并要右边乘以左边,因为矩阵不满足交换律。还有可以把3*3*3的矩阵乘法优化成2*2*3,毕竟最后一行都是相同的且前两个肯定都是零。


代码:

#include<algorithm>#include<cstdio>#include<cstring>#include<iostream>#include<queue>#define inf 0x3f3f3f3f#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;typedef long long ll;const int mx = 1e5+10,mod = 1e9+7;struct data{    ll marx[3][3];}ma[mx<<2][2];const data da[2] = {{1,0,0,1,1,1,0,0,1},{1,1,1,0,1,0,0,0,1}};bool lazy[mx<<2];char str[mx];ll ans1,ans2;int n,m;void push_up(int rt){    int rt1 = rt<<1,rt2 = rt1|1;    int t1 = lazy[rt1],t2 = lazy[rt2],n1 = t1^1,n2 = t2^1;    for(int i=0;i<2;i++){        for(int j=0;j<3;j++){            ll c=0;            for(int k=0;k<2;k++)            c = (c+ma[rt2][t2].marx[i][k]*ma[rt1][t1].marx[k][j]%mod)%mod;            ma[rt][0].marx[i][j] =c;        }        ma[rt][0].marx[i][2] = (ma[rt][0].marx[i][2] + ma[rt2][t2].marx[i][2])%mod;    }    for(int i=0;i<2;i++){        for(int j=0;j<3;j++){            ll c=0;            for(int k=0;k<2;k++)            c = (c+ma[rt2][n2].marx[i][k]*ma[rt1][n1].marx[k][j])%mod;            ma[rt][1].marx[i][j] =c;        }        ma[rt][1].marx[i][2] = (ma[rt][1].marx[i][2] + ma[rt2][n2].marx[i][2])%mod;    }}void build(int l,int r,int rt){    lazy[rt] = 0;    ma[rt][0].marx[2][2] = ma[rt][1].marx[2][2] = 1;    if(r==l){        int c = str[r]-'0';        ma[rt][0] = da[c],ma[rt][1] = da[c^1];        return ;    }    int mid = (l+r)>>1;    build(lson);    build(rson);    push_up(rt);}void push_down(int rt){    if(lazy[rt]){        lazy[rt<<1] ^= 1;        lazy[rt<<1|1] ^= 1;        lazy[rt] = 0;    }}void update(int L,int R,int l,int r,int rt){    if(L<=l&&R>=r) { lazy[rt] ^= 1; return ; }    push_down(rt);    int mid = (l+r)>>1;    if(mid>=L) update(L,R,lson);    if(mid<R) update(L,R,rson);    push_up(rt);}void query(int L,int R,int l,int r,int rt){    if(L<=l&&R>=r){        ll nx,ny;        bool ts = lazy[rt];        nx = ma[rt][ts].marx[0][0]*ans1%mod;        nx = (nx+ma[rt][ts].marx[0][1]*ans2+ma[rt][ts].marx[0][2])%mod;        ny = ma[rt][ts].marx[1][0]*ans1%mod;        ny = (ny+ma[rt][ts].marx[1][1]*ans2+ma[rt][ts].marx[1][2])%mod;        ans1 = nx,ans2 = ny;        return ;    }    int mid = (l+r)>>1;    push_down(rt);    if(mid>=L) query(L,R,lson);    if(mid<R) query(L,R,rson);    push_up(rt);}int main(){    int t;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        scanf("%s",str+1);        build(1,n,1);        while(m--){            int x,y,z;            scanf("%d%d%d",&x,&y,&z);            if(x&1) update(y,z,1,n,1);            else{                ans1 = ans2 = 0;                query(y,z,1,n,1);                printf("%lld\n",(ans1+ans2)%mod);            }        }    }    return 0;}


原创粉丝点击