这是一道普及组的题目……不要拦着我,我要跳楼……
首先我们可以轻松写出状态转移方程:f[i]=Σf[j] (j<=i&&s[j]<=s[i],其中s表示前缀和)
这个DP的时间复杂度是O(n^2)的,显然过不了这题。
然后我们就考虑有没有一种数据结构可以统计一个限度内的前缀和,显然树状数组满足了我们的要求。
于是这题就A掉啦……
p.s.这题的权值可能较大,记得在对权值离散化一下。
再次p.s.记得考虑1~i这些元素分成一段的可能。
附上AC代码:
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=1e5+10,p=1e9+9;
struct note{
int w,wz;
bool operator < (const note &lyf) const {return w==lyf.w?wz<lyf.wz:w<lyf.w;}
}a[N];
int n,x,num[N],t[N],f[N];
inline char nc(void){
static char ch[100010],*p1=ch,*p2=ch;
return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &a){
static char c=nc();int f=1;
for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
for (a=0;isdigit(c);a=(a<<3)+(a<<1)+c-'0',c=nc());
a*=f;return;
}
#define lowbit(x) (x&-x)
inline int get(int x){int sum=0;for (int i=x; i; i-=lowbit(i)) sum=(sum+t[i])%p;return sum;}
inline void add(int x,int y){for (int i=x; i<=n; i+=lowbit(i)) t[i]=(t[i]+y)%p;return;}
int main(void){
read(n);
for (int i=1; i<=n; ++i) read(x),a[i]=(note){a[i-1].w+x,i};
sort(a+1,a+1+n);
for (int i=1; i<=n; ++i) num[a[i].wz]=i;
for (int i=1; i<=n; ++i) add(num[i],f[i]=((a[num[i]].w>=0)+get(num[i]))%p);
printf("%d\n",f[n]);
return 0;
}