hdu 6155(线段树+dp+矩阵)

Given a binary string S[1,…,N]S[1,…,N] (i.e. a sequence of 0’s and 1’s), and QQ queries on the string.

There are two types of queries:

  1. Flipping the bits (i.e., changing all 1 to 0 and 0 to 1) between ll and rr (inclusive).
  2. Counting the number of distinct subsequences in the substring S[l,…,r]S[l,…,r].
    Input
    The first line contains an integer TT, denoting the number of the test cases.

For each test, the first line contains two integers NN and QQ.

The second line contains the string SS.

Then QQ lines follow, each with three integers typetype, ll and rr, denoting the queries.

1≤T≤51≤T≤5

1≤N,Q≤1051≤N,Q≤105

S[i]∈{0,1},∀1≤i≤NS[i]∈{0,1},∀1≤i≤N

type∈{1,2}type∈{1,2}

1≤l≤r≤N1≤l≤r≤N
Output
For each query of type 2, output the answer mod (109+7109+7) in one line.
Sample Input
2
4 4
1010
2 1 4
2 2 4
1 2 3
2 1 4
4 4
0000
1 1 2
1 2 3
1 3 4
2 1 4
Sample Output
11
6
8
10

题意是给一个01字符串,然后有2种操作,
1、把l到r这个区间的字符翻转,
2、查询l到r这个区间有多少个不同的子序列,(注意是子序列,可不连续),对1e9+7取模

先考虑dp求01串的不同子序列的个数。

对于操作2 可以得到 dp方程
如果s[i]==0 dp[i][0]=dp[i-1][1]+dp[i-1][0]+1;
不同的子序列个数就是i-1位置 是1或者0结尾的所有的串加上这一位,那么所有的串至少长度为2,再加上它自身,那么长度为1的只有它自身

所以当 s[i]==0 dp[i][0]=dp[i-1][1]+dp[i-1][0]+1;
dp[i][1]=dp[i-1][1];

s[i]=1 dp[i][1]=dp[i-1][1]+dp[i-1][0]+1;
dp[i][0]=dp[i-1][0];

得到矩阵 这里写图片描述

那么关于序列翻转,就是相当于矩阵翻转,把A矩阵变成B矩阵就好,把序列翻转的结果,就是如果这是1矩阵 那么被矩阵相乘 要有0矩阵的效果,就是中间列和第一列互换,同时dp[i][0]和dp[i][1]结果互换。。加上翻转标记就好

#include <bits/stdc++.h>
using namespace std;
const int SIZE = 3;
const int N = 1e5+100;
const int mod = 1e9+7;
typedef long long ll;
struct Matrix
{
    ll m[SIZE][SIZE];
    friend Matrix operator* (const Matrix& a, const Matrix& b)
    {
        Matrix c;
        for (int i = 0; i < SIZE; i++)
            for (int j = 0; j < SIZE; j++)
            {
                c.m[i][j] = 0;
                for (int k = 0; k < SIZE; k++)
                    c.m[i][j] += a.m[i][k] * b.m[k][j] % mod;
                c.m[i][j] %= mod;
            }
        return c;
    }
};

int filp[N*4],a[N];
Matrix sum[N*4];

Matrix s[2]={{1,0,0,1,1,0,1,0,1},{1,1,0,0,1,0,0,1,1}};

void out(int rt)
{
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        cout<<sum[rt].m[i][j]<<" ";
        cout<<endl;
    }
}

void build(int l,int r,int rt)
{
    filp[rt]=0;
    if(l==r)
    {
        sum[rt]=s[a[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    sum[rt]=sum[rt<<1]*sum[rt<<1|1];
    // cout<<(rt<<1)<<endl;
    // out(rt<<1);
    // cout<<(rt<<1|1)<<endl;
    // out(rt<<1|1);
    // cout<<rt<<endl;
    // out(rt);
}

void huan(int rt)
{
    swap(sum[rt].m[0][0],sum[rt].m[0][1]);
    swap(sum[rt].m[1][0],sum[rt].m[1][1]);
    swap(sum[rt].m[2][0],sum[rt].m[2][1]);
    swap(sum[rt].m[0][0],sum[rt].m[1][0]);
    swap(sum[rt].m[0][1],sum[rt].m[1][1]);
}


void pushdown(int rt)
{
    if(filp[rt])
    {
        huan(rt<<1);
        huan(rt<<1|1);
        filp[rt<<1]^=1;
        filp[rt<<1|1]^=1;
        filp[rt]=0;
    }
}


void update(int l,int r,int L,int R,int rt)
{
    if(L<=l&&R>=r)
    {
        huan(rt);
        filp[rt]^=1;
        return ;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid) update(l,mid,L,R,rt<<1);
    if(R>mid) update(mid+1,r,L,R,rt<<1|1);
    sum[rt]=sum[rt<<1]*sum[rt<<1|1];
}

Matrix query(int l,int r,int L,int R,int rt)
{
    if(L<=l&&R>=r)
    {
        return sum[rt];
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    Matrix res={1,0,0,0,1,0,0,0,1};
    if(L<=mid) res=res*query(l,mid,L,R,rt<<1);
    if(R>mid) res=res*query(mid+1,r,L,R,rt<<1|1);
    sum[rt]=sum[rt<<1]*sum[rt<<1|1];
    return res;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%1d",&a[i]);
        build(1,n,1);
        while(m--)
        {
            int op,L,R;
            scanf("%d%d%d",&op,&L,&R);
            if(op==2){
                Matrix ans=query(1,n,L,R,1);
                Matrix hh={0,0,1,0,0,0,0,0,0};
                hh=hh*ans;
                printf("%lld\n",(hh.m[0][0]+hh.m[0][1] )%mod);
            }
            else if(op==1)
                update(1,n,L,R,1);
        }
    }
}
posted @ 2017-09-19 21:17  黑码的博客  阅读(83)  评论(0编辑  收藏  举报