[樹狀數組優化DP] HLOJ539. 人品累加和

題解

題目描述
人品是必不可少的,人品還是守恆的。每個人的人品都是不同的,並且有正的(選擇題可以用骰子全過),也有負的。
海亮高級中學有n (1<=n<=100,000) 個學生,第i個人的人品值是Ai(10,000<=Ai<=10,000).
海亮高級中學決定重新規劃寢室,要讓每個寢室的人品和不小於0.寢室的人品和是這個寢室裏所有人的人品和。
因爲名單是按照學籍號給出的,所以,現在你不能調整學生的順序,只能按照輸入的順序把學生依次分進各個寢室,當然,爲了增加難度,每個寢室的人數可以不同,我們甚至可以把n個學生放在同一個寢室。我們的口號,人品比宿舍重要。
比如現在有4個人,人品分別是2, 3, -3, 1。我們可以按照下面分寢室:
(2 3 -3 1)
(2 3 -3) (1)
(2) (3 -3 1)
(2) (3 -3) (1)
這樣保證每個寢室的人品和不小於0.
現在的問題是,如果按照這種原則,有多少種分寢室的方法。當然,方法可能很多,你只需要輸出方案數對 1,000,000,009 取餘數即可。
輸入格式
第一行一個整數n
接下來n行,表示每個學生的人品Ai .

題解

我們先搞這道題的樸素dp

狀態

s[i] 是前i個人的人品累加和。
這個狀態比較好做f[i] 代表前i個人的分配方式,
所以有f[i]=f[j](s[j]<=s[i],j<=i)f[0]=1

優化

所以只要用樹狀數組弄出所有的f[j] 就行了。
不過要記得離散化。

code

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int num=0;char c=' ';bool flag=true;
    for(;c>'9'||c<'0';c=getchar())
        if(c=='-')
            flag=false;
    for(;c>='0'&&c<='9';num=(num<<3)+(num<<1)+c-48,c=getchar());
    return flag ? num : -num;
}
const int maxn=100020,p=1000000009;
int n;
struct S{
    int v,id;
}s[maxn];
bool mycmp(S a,S b){
    return a.v<b.v;
}
void init(){
    n=read();
    for(int i=1;i<=n;i++){
        s[i].v=read()+s[i-1].v;
        s[i].id=i;
    }
}
int pos[maxn];
void LSH(){
    sort(s,s+n+1,mycmp);
    int cnt=1,t=0;
    for(int i=0;i<=n;i++)
        if(s[i].v==s[t].v)pos[s[i].id]=cnt;
    else{
        pos[s[i].id]=++cnt;
        t=i;
    }
}//離散化
namespace shuzhuangshuzu{
    int lowbit(int t){return t&-t;}
    int ans,d[maxn];
    int find(int x){
        int t=0;
        while(x){
            t+=d[x];
            x-=lowbit(x);
            t%=p;
        }
        return t;
    }//查詢和
    void updata(int x,int v){
        while(x<=n){
            d[x]+=v;
            d[x]%=p;
            x+=lowbit(x);
        }
    }//更新數據,x的位置加上v。
}using namespace shuzhuangshuzu;
void dp(){
    updata(pos[0],1);
    for(int i=1;i<=n;i++){
        ans=find(pos[i]);
        updata(pos[i],ans);
    }
}
int main(){
    init();
    LSH();
    dp();
    printf("%d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章