【JZOJ A组】神在夏至祭降下了神谕

Description

【JZOJ A组】神在夏至祭降下了神谕_第1张图片

Input

这里写图片描述

Output

这里写图片描述

Sample Input

4 1
0 0 1 1

Sample Output

5

Data Constraint

【JZOJ A组】神在夏至祭降下了神谕_第2张图片

Hint

【JZOJ A组】神在夏至祭降下了神谕_第3张图片

思路

显然用DP
设 f[i]表示第 1~i 个数分段的方案数。
转移固然是符合要求就转。

可以用数据结构维护,我用了线段树

代码

#include
#include
#include
using namespace std;
const int maxn=1e5+77,mod=1e9+7;
int n,k,s[maxn],a[maxn*8],ss=0,f[maxn];
void ins(int v,int l,int r,int p,int val)
{
    if(l==r)
    {
        a[v]=(a[v]+val)%mod; return; 
    }
    int mid=(l+r)>>1;
    if(p<=mid) ins(v*2,l,mid,p,val); else ins(v*2+1,mid+1,r,p,val);
    a[v]=(a[v*2]+a[v*2+1])%mod;
}
void query(int v,int l,int r,int ll,int rr)
{
    if(l==ll&&r==rr)
    {
        ss=(ss+a[v])%mod; return;
    }
    int mid=(l+r)>>1;
    if(rr<=mid) query(v*2,l,mid,ll,rr);else if(ll>mid) query(v*2+1,mid+1,r,ll,rr); else
    {
        query(v*2,l,mid,ll,mid); query(v*2+1,mid+1,r,mid+1,rr);
    }
}
int main()
{
    scanf("%d%d",&n,&k);
    int x;
    for(int i=1; i<=n; i++) scanf("%d",&x),s[i]=s[i-1]+(x?1:-1);
    ins(1,0,2*n,n,1);
    for(int i=1; i<=n; i++)
    {
        x=s[i]+n;
        ss=0; query(1,0,2*n,max(0,x-k),min(x+k,2*n));
        f[i]=ss; ins(1,0,2*n,x,ss);
    }
    printf("%d",f[n]);
}

你可能感兴趣的:(题解,dp,线段树)