zoukankan      html  css  js  c++  java
  • 【USACO】奶牛抗议 树状数组+dp

    题目描述

    约翰家的 N 头奶牛正在排队游行抗议。一些奶牛情绪激动,约翰测算下来,排在第 i 位的奶牛
    的理智度为 A i ,数字可正可负。
    约翰希望奶牛在抗议时保持理性,为此,他打算将这条队伍分割成几个小组,每个抗议小组的理
    智度之和必须大于或等于零。奶牛的队伍已经固定了前后顺序,所以不能交换它们的位置,所以分在
    一个小组里的奶牛必须是连续位置的。除此之外,分组多少组,每组分多少奶牛,都没有限制。
    约翰想知道有多少种分组的方案,由于答案可能很大,只要输出答案除以 1000000009 的余数即
    可。

    输入

    • 第一行:单个整数 N,1 ≤ N ≤ 100000
    • 第二行到第 N + 1 行:第 i + 1 行有一个整数 A i ,−10 5 ≤ A i ≤ 10 5

    输出

    • 单个整数:表示分组方案数模 1000000009 的余数

    样例输入

    4 2 3 -3 1

    样例输出

    4

    提示

    如果分两组,可以把前三头分在一组,或把

    后三头分在一组;如果分三组,可以把中间两头

    分在一组,第一和最后一头奶牛自成一组;最后

    一种分法是把四头奶牛分在同一组里。
     
     
    题解:
    朴素做法 if(sum[i]-sum[j]>=0)f[i]+=f[j].
    于是发现只要sum[j]<=sum[i] 即可转移
    然后以sum[i]为下标,维护树状数组即可,没事可以离散化一下.
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long ll;
     7 const int mod=1000000009,N=100005;
     8 int gi(){
     9     int str=0,f=1;char ch=getchar();
    10     while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0' && ch<='9')str=str*10+ch-48,ch=getchar();
    12     return str*f;
    13 }
    14 int a[N],id[N],n;ll Tree[N*4],sum[N],b[N],f[N];
    15 int pf(ll x)
    16 {
    17     int l=1,r=n,mid;
    18     while(l<=r)
    19     {
    20         mid=(l+r)>>1;
    21         if(b[mid]==x)return mid;
    22         if(x>b[mid])l=mid+1;
    23         else r=mid-1;
    24     }
    25     return 0;
    26 }
    27 void add(int sta,ll x){for(int i=sta;i<=n;i+=(i&(-i)))Tree[i]+=x,Tree[i]%=mod;}
    28 ll getsum(int sta)
    29 {
    30     ll sum=0;
    31     for(int i=sta;i>=1;i-=(i&(-i)))sum+=Tree[i],sum%=mod;
    32     return sum;
    33 }
    34 int main()
    35 {
    36     n=gi();
    37     for(int i=1;i<=n;i++)a[i]=gi(),sum[i]=sum[i-1]+a[i],b[i]=sum[i];
    38     sort(b+1,b+n+1);
    39     for(int i=1;i<=n;i++)
    40     {
    41         id[i]=pf(sum[i]);
    42     }
    43     for(int i=1;i<=n;i++)
    44     {
    45         f[i]=getsum(id[i]);
    46         if(sum[i]>=0)f[i]++;
    47         f[i]%=mod;
    48         add(id[i],f[i]);
    49     }
    50     printf("%lld",f[n]%mod);
    51     return 0;
    52 }
  • 相关阅读:
    Linux文件权限
    Linux命令
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7053785.html
Copyright © 2011-2022 走看看