題意:
找出所有的美麗序列。美麗序列就是相鄰的元素絕對值之差不超過d的序列。
分析:
dp[i]表示到i爲止滿足情況的種類數。
dp[i]=sum(dp[j] abs(a[j]-a[i])<=d);
當然這個數據量很大,直接按照方程的話複雜度爲O(n*n). 所以要利用其他方式,樹狀數組。這裏需要對元素離散化,因爲d很大。剛開始想的時候以爲二維的DP可以,但是存儲空間不允許。後來一直不明白的問題是如何證明:
dp[i]=sum(dp[j] abs(a[j]-a[i])<=d);
假如 1 3 5 7 滿足序列,那麼美麗序列就有{1,3}{3,5}{5,7}{1,3,5}{3,5,7}{1,3,5,7} 分別爲兩個元素的情況,三個元素的情況,四個元素的情況。當然我們數的時候會這樣想,但是計算的時候就不能這樣想了。首先加入樹狀數組之前,先求出滿足條件的種類數,那麼這個數就要加入到這些合法的序列後面才合法,而這些合法的序列的由來又有很多種方式+1(只有自己),所以結果還是遞推出來的。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<utility>
#include <map>
#include<cstring>
#include<vector>
#include<deque>
#include<queue>
#include<stack>
#include<algorithm>
#include<stdlib.h>
#define read freopen("q.txt","r",stdin)
#define LL long long
const int maxn =100005;
const double inf=2000000000.0;
const int mod=9901;
using namespace std;
int c[maxn],a[maxn],hs[maxn];
int cnt,n;
int lowbit(int x)
{
return x&(-x);
}
int getSum(int x)
{
int sum=0;
for(int i=x;i>0;i-=lowbit(i))
{
sum+=c[i];
sum%=mod;
}
return sum;
}
void update(int x,int val)
{
for(int i=x;i<=n;i+=lowbit(i))
{
c[i]+=val;
}
}
int low(int x)
{
int l=1,r=cnt;
while(l<=r)
{
int mid=(l+r)/2;
if(hs[mid]<x)l=mid+1;
else r=mid-1;
}
return r+1;
}
int up(int x)
{
int l=1,r=cnt;
while(l<=r)
{
int mid=(l+r)/2;
if(hs[mid]<=x)l=mid+1;
else r=mid-1;
}
return l-1;
}
int main()
{
int d,i,j;
while(~scanf("%d%d",&n,&d))
{
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
{
scanf("%d",a+i);
hs[i]=a[i];
}
sort(hs+1,hs+n+1);
cnt=1;
for(i=2;i<=n;i++)if(hs[i]!=hs[cnt])hs[++cnt]=hs[i];
int sum=0;
for(i=1;i<=n;i++)
{
int x=low(a[i]-d),y=up(a[i]+d),z=low(a[i]);
int tmp=getSum(y)-getSum(x-1);
tmp+=mod;
tmp%=mod;
/////////////// cout<<"TTTTmp = "<<tmp<<endl;
sum=(sum+tmp)%mod;
update(z,tmp+1);
// cout<<"sum = "<<sum<<endl;
}
cout<<sum<<endl;
}
}