f[i]=∑f[j] (sum[j]<=sum[i]).
sum为前缀和.
裸的DP是O(N^2)的,其实我们要找的j只需满足sum[j]<=sum[i],然后求和.
而树状数组天生就是干这个的.范围大,离散化一下就好了.
code:
/**************************************************************
Problem: 2274
User: exponent
Language: Pascal
Result: Accepted
Time:140 ms
Memory:2568 kb
****************************************************************/
const maxn=100001;
mo=1000000009;
var s,t,p,q,f,c:array[0..maxn] of longint;
n,i,num,pre,pos,rank:longint;
procedure swap(var a,b:longint);
var temp:longint;
begin
temp:=a; a:=b; b:=temp;
end;
procedure sort(l,r:longint);
var i,j,mid:longint;
begin
i:=l; j:=r;
mid:=s[(l+r)>>1];
while i<=j do
begin
while s[i]<mid do inc(i);
while s[j]>mid do dec(j);
if i<=j then
begin
swap(s[i],s[j]);
swap(p[i],p[j]);
inc(i); dec(j);
end;
end;
if i<r then sort(i,r);
if j>l then sort(l,j);
end;
function lowbit(i:longint):longint;
begin
lowbit:=i and (i xor (i-1));
end;
procedure change(i,delta:longint);
begin
while i<=maxn do
begin
c[i]:=(c[i]+delta) mod mo;
inc(i,lowbit(i));
end;
end;
function getsum(i:longint):longint;
begin
getsum:=0;
while i>0 do
begin
getsum:=(getsum+c[i]) mod mo;
dec(i,lowbit(i));
end;
end;
begin
readln(n);
for i:=1 to n do
begin
readln(num);
s[i]:=s[i-1]+num;
p[i]:=i;
q[i]:=s[i];
end;
sort(1,n);
pre:=s[1];
t[p[1]]:=1;
rank:=1;
for i:=2 to n do
if s[i]=pre then t[p[i]]:=rank
else
begin
pre:=s[i];
inc(rank);
t[p[i]]:=rank;
end;
f[0]:=1;
change(1,1);
for i:=1 to n do
if q[i]>=0 then
begin
f[i]:=getsum(t[i]);
change(t[i],f[i]);
end;
writeln(f[n]);
end.