[樹狀數組+DP]hdu3450 Counting Sequences

題意:
找出所有的美麗序列。美麗序列就是相鄰的元素絕對值之差不超過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;

    }
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章