版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/82831473
分析:
很容易想到DP,设 表示已经处理了前i个,末尾一个属于A集合/B集合。
那么
,其中
满足以下条件:
1、
2、
3、
然后用前缀和优化水过去就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 100010
#define MOD 1000000007
using namespace std;
typedef long long ll;
ll a[MAXN],A,B;
int n,lasA1[MAXN],lasB1[MAXN];
ll dp[MAXN][2],sum0[MAXN],sum1[MAXN];
int find(ll val){
int l=1,r=n,res=0;
while(l<=r){
int mid=(l+r)>>1;
if(a[mid]<=val){
res=mid;
l=mid+1;
}
else
r=mid-1;
}
return res;
}
int main(){
//freopen("division.in","r",stdin);
//freopen("division.out","w",stdout);
SF("%d%lld%lld",&n,&A,&B);
for(int i=1;i<=n;i++)
SF("%lld",&a[i]);
for(int i=1;i<=n;i++){
lasA1[i]=lasA1[i-1];
lasB1[i]=lasB1[i-1];
if(a[i]-a[i-1]<A||i==1)
lasA1[i]=i;
if(a[i]-a[i-1]<B||i==1)
lasB1[i]=i;
}
sum0[0]=sum1[0]=1;
for(int i=1;i<=n;i++){
sum0[i]=sum0[i-1];
sum1[i]=sum1[i-1];
int i1=lasA1[i]-1;
int i2=find(a[i+1]-B);
if(i==n)
i2=n;
if(i1<=i2){
if(i1==0)
dp[i][0]=sum1[i2];
else
dp[i][0]=(sum1[i2]-sum1[i1-1]+MOD)%MOD;
}
// PF("<%d %d>\n",i1,i2);
i1=lasB1[i]-1;
i2=find(a[i+1]-A);
if(i==n)
i2=n;
if(i1<=i2){
if(i1==0)
dp[i][1]=sum0[i2];
else
dp[i][1]=(sum0[i2]-sum0[i1-1]+MOD)%MOD;
}
//PF("[%d %d]\n",i1,i2);
/*if(dp[i][0]!=0){
PF("{%lld %lld}\n",dp[i][0],dp[i][1]);
PF("--------\n");
}*/
sum0[i]=(sum0[i-1]+dp[i][0])%MOD;
sum1[i]=(sum1[i-1]+dp[i][1])%MOD;
}
PF("%lld",(dp[n][0]+dp[n][1])%MOD);
}