• 奶牛抗议


    题目描述

    约翰家的 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

    提示

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

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

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

    一种分法是把四头奶牛分在同一组里。
    题解:
     动态规划+树状数组+离散化
    不难列出
    f[i]=sum(f[j]|sum[i]-sum[j]>0)
    sum[i]-sum[j]>0→sum[i]>sum[j]
    转化为求sum[j]小于sum[i]的f[j]的和
    f[i]=sum(f[j]|sum[i]>sum[j])
    是不是很眼熟?
    树状数组存小于x的f的和
    则f[i]=getsum(sum[i]);
       add(sum[i],f[i])即可.
    由于sum值太大,要用离散化。
    据yzd大佬说:此题可以不用离散,大致是按sum排序
    f[i]=getsum(i);
    add(i,f[i]);
    没有代码实现,读者可以自己思考一下。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int d[1000005],f[100005],n,sum[100005],p[100005],maxx;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int x,int c)
    {
        while (x<=1000000)
        {
            d[x]+=c;
            d[x]%=1000000009;
            x+=lowbit(x);
        }
    }
    int query(int x)
    {
        int s=0;
        while (x>0)
        {
            s+=d[x];
            s%=1000000009;
            x-=lowbit(x);
        }
        return s%1000000009;
    }
    int binary(int x)
    {
        int l=1,r=n+1;
         while (l<r)
         {
            int mid=(l+r)/2;
             //if (p[mid]==x) return l;
             if (p[mid]>=x) r=mid;
             else l=mid+1;
         }
        return l;
    }
    int main()
    {int i;
    //freopen("file.in","r",stdin);
        scanf("%d",&n);
         for (i=1;i<=n;i++)
          {
             scanf("%d",&sum[i]);
             sum[i]+=sum[i-1];
             p[i]=sum[i];
              
          }
          p[n+1]=0;
        sort(p+1,p+n+2);
    //  for (i=1;i<=n;i++)
    //   sum[i]=binary(sum[i]);
      add(binary(0),1);
       for (i=1;i<=n;i++)
       {
         f[i]=query(binary(sum[i]));
         f[i]%=1000000009;
          add(binary(sum[i]),f[i]);
           
       }
    cout<<f[n]%1000000009;
    }
  • 相关阅读:
    深入理解TCP、UDP协议及两者的区别
    Java多线程之Executor框架
    Java中的线程池及其实现类ThreadPoolExecutor
    深入理解java虚拟机之Java对象头
    深入理解Java虚拟机之创建对象,即创建一个类的过程
    使用RedisTemplate操作Redis数据库
    深入理解Java虚拟机之运行时数据区域
    多线程之join方法
    线程之间的通信方式:wait/notify
    多线程之可见性:volatile
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7050869.html
Copyright © 2020-2023  润新知