【洛谷】2344 奶牛抗议 DP+树状数组

来源:互联网 发布:手机点菜软件免费版 编辑:程序博客网 时间:2024/06/11 11:27

题目传送门

这是一道普及组的题目……不要拦着我,我要跳楼……

首先我们可以轻松写出状态转移方程: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;}

原创粉丝点击