原題連結
題解
1.觀察資料法:看到 \(1e^5\) 想到線性遞推,想到遍歷每頭奶牛試著在它們後面新增隔斷時的分組方案數
2.對於奶牛 \(i\) 它的狀態轉移方程為 \(dp[i]+=dp[j];j<i;sum[j]<=sum[i]\)
3.上述可以把 \(sum\) 看成 x軸, \(dp\) 看成 \(f(x)\),這樣就變成了求小於 \(sum[i]\) 的所有 \(dp[i]\) 的區間求和,而對 \(sum[i]\) 上的 \(dp[i]\) 修改又是單點修改,所以考慮樹狀陣列
4.由於有負數,所以要離散化,注意開頭的零也要離散化進去
code
#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
const ll mod=1e9+9;
using namespace std;
ll dp[100005]={0};
ll tree[100005]={0};
ll haxi[100005]={0};
ll n;
ll pre[100005]={0},pre_sort[100005]={0};
ll len=0;
ll query(ll x)
{
ll sum=0;
while(x)
{
sum+=tree[x];
sum%=mod;
x-=lowbit(x);
}
return sum;
}
void update(ll x,ll val)
{
while(x<=len)
{
tree[x]+=val;
tree[x]%=mod;
x+=lowbit(x);
}
}
int main()
{
cin>>n;
for(ll i=1;i<=n;i++)
{
cin>>pre[i];
pre[i]+=pre[i-1];
pre_sort[i]=pre[i];
}
sort(pre_sort,pre_sort+1+n);
len=unique(pre_sort,pre_sort+1+n)-pre_sort;//離散化操作,由於前面的隔斷可以選零點後面,所以零點也算上隔斷
for(int i=0;i<=n;i++) haxi[i]=lower_bound(pre_sort,pre_sort+len,pre[i])-pre_sort+1;//離散化,+1代表第幾小
update(haxi[0],1);
for(ll i=1;i<=n;i++)
{
dp[i]=query(haxi[i]);
update(haxi[i],dp[i]);
}
//for(int i=1;i<=n;i++) printf("dp:%d\n",dp[i]);
cout<<dp[n];
return 0;
}
//對於每個i,求所有滿足presj<presi的dp[j]和,把pres看成下標x,dp看成f(x),則變成求pres-f(x)
//實際上我們只需要直到pres的相對大小即可,所以把他們離散化