• 洛谷P2344 奶牛抗议


    题目背景

    Generic Cow Protests, 2011 Feb

    题目描述

    约翰家的N 头奶牛正在排队游行抗议。一些奶牛情绪激动,约翰测算下来,排在第i 位的奶牛的理智度为Ai,数字可正可负。

    约翰希望奶牛在抗议时保持理性,为此,他打算将这条队伍分割成几个小组,每个抗议小组的理智度之和必须大于或等于零。奶牛的队伍已经固定了前后顺序,所以不能交换它们的位置,所以分在一个小组里的奶牛必须是连续位置的。除此之外,分组多少组,每组分多少奶牛,都没有限制。

    约翰想知道有多少种分组的方案,由于答案可能很大,只要输出答案除以1000000009 的余数即可。

    输入输出格式

    输入格式:

    • 第一行:单个整数N,1 ≤ N ≤ 100000

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    4
    2
    3
    -3
    1
    输出样例#1:
    4

    说明

    解释:如果分两组,可以把前三头分在一组,或把后三头分在一组;如果分三组,可以把中间两头分在一组,第一和最后一头奶牛自成一组;最后一种分法是把四头奶牛分在同一组里。

    分析:求方案数的解决方法可以用数学方法和dp,这道题我找不出数学数学方法来,只能dp.本来我的状态考虑为f[i][j]表示前j头牛分i组,可是这个i并不确定,而且O(n^3)的dp,直接超时了,那么我们去掉这一维,f[i]表示前i头牛的分组,f[i]=∑f[j](a[j] + a[j + 1] +...+a[i] >= 0),转换成前缀和就是s[j] <= s[i],那么怎么找j < i并且s[j] <= s[i]的数呢?当然是树状数组啦!但是由于s可能过大,需要先离散化一下.

    dp中如果状态中的一维不能确定,可以省去这一维,通常可以用树状数组优化满足两个条件i<j&&s[i]<s[j]的题,数据太大需要离散化.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int mod = 1000000009;
    
    int n,cnt = 1,ans,c[100010];
    
    struct node
    {
         int a,id,newid;    
    }e[100010];
    
    bool cmp(node a,node b)
    {
        return a.a < b.a;
    }
    
    bool cmp2(node a,node b)
    {
        return a.id < b.id;
    }
    
    void add(int x,int d)
    {
        while (x <= cnt)
        {
            c[x] = (c[x] + d) % mod;
            x += x & (-x);
        }
    }
    
    int query(int x)
    {
        int res = 0;
        while (x)
        {
            res = (res + c[x]) % mod;
            x -= x & (-x);
        }
        return res;
    }
    
    int main()
    {
        scanf("%d",&n);
        e[0].a = 0;
        e[0].id = 0;
        for (int i = 1;i <= n; i++)
        {
        int t;
        scanf("%d",&t);
        e[i].a = e[i-1].a + t; 
        e[i].id = i;
        }
        sort(e,e + 1 + n,cmp);
        e[0].newid = 1;
        for (int i = 1; i <= n; i++)
        {
            if (e[i].a != e[i-1].a)
            e[i].newid = ++cnt;
            else
            e[i].newid = cnt;
        }
        sort(e,e + 1 + n,cmp2);
        add(e[0].newid,1);
        for (int i = 1; i <= n; i++)
        {
            ans = query(e[i].newid);
            add(e[i].newid,ans);
        }
        printf("%d
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
    【ASP.NET Core】自己编程来生成自签名的服务器证书
    WPF:DataGrid可过滤、多语言
    将python脚本打包为exe可执行文件
    C# WPF DATAGRID 分组(GROUP)
    皮肤样式备份
    wpf – 如何在UIElement.Margin上为绑定设置FallbackValue?
    Wpf虚拟屏幕键盘
    ubuntu docker 安装 redis
    fastapi 返回请求头信息
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7507395.html
Copyright © 2020-2023  润新知