[树状数组][DP]JZOJ 4738 神在夏至祭降下了神谕
分析
状态转移方程显然:
f[i]=∑f[j] (|s[i]-s[j-1]|≤k)
发现如果i向后移一位,那么整个区间整体要不+1要不-1
那么可以直接减掉k作为树状数组中的下标,用树状数组求出符合的和即可
#include <iostream> #include <cstdio> #define lowbit(x) x&-x using namespace std; typedef long long ll; const int N=2e5; const ll P=1e9+7; ll c[2*N+1],s[N],f[N]; int n,k; void Add(int x,ll dat) { for (int i=x+N;i<=2*N;i+=lowbit(i)) (c[i]+=dat)%=P; } ll Get_Sum(int x) { ll ans=0; for (int i=x+N;i;i-=lowbit(i)) (ans+=c[i])%=P; return ans; } int main() { scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) { int a; scanf("%d",&a); s[i]=s[i-1]+(!a?1:-1); } Add(0,1); for (int i=1;i<=n;i++) f[i]=(Get_Sum(s[i]+k)-Get_Sum(s[i]-k-1)+P)%P,Add(s[i],f[i]); printf("%lld",f[n]); }
在日渐沉没的世界里,我发现了你。