zoukankan      html  css  js  c++  java
  • 前缀和?or差分序列?

    前缀和数组是十分基本和简单的一种工具,但是要想真正用好,却不容易。在平时的训练中有很多的问题都要用到前缀和。我们通过一个小的例子来看一下

    cogs1190最大和

    题目大意:N个数围成一圈,要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,问能形成的最大的和。

    思路:一看到这个题,竟然想到了线段树,后来发现有点大材小用,要是深究的话也不是很会写,于是就另辟蹊径。这个题目中有一个神奇的关系就是这是个环,于是我们就有了两种情况:1)这一段数本身就在给定区间内;2)这一段数被分放在给定区间的两端。第一种情况比较好处理,只用前缀和,跟新最小值和最大的差就可以了;后一种情况就要用到后缀和,找到最大值和后缀和的和取最大。输出最大值就可以了。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int sum1[100001]={0},sum2[100001]={0},a[100001]={0};
    int main()
    {
        freopen("maxsum.in","r",stdin);
        freopen("maxsum.out","w",stdout);
        
        int n,i,j,maxn,minn;
        maxn=-2100000000;
        scanf("%d",&n);
        for (i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            sum1[i]=sum1[i-1]+a[i];
        }
        for (i=n;i>=1;--i)
            sum2[i]=sum2[i+1]+a[i];
        minn=2100000000;
        for (i=1;i<=n;++i)
        {
            if (sum1[i]-minn>maxn) maxn=sum1[i]-minn;
            if (sum1[i]<minn) minn=sum1[i];    
        }
        minn=-2100000000;
        for (i=1;i<=n;++i)
        {
            if (minn+sum2[i]>maxn) maxn=minn+sum2[i];
            if (sum1[i]>minn) minn=sum1[i];
        }
        printf("%d
    ",maxn);
        
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    这样一道题目中展现了前缀和的特殊魅力,以后还要多加练习,熟练应用。

    现在才知道,这个二级前缀和数组好像是一种高端的东西,差分序列。

    cogs1435金发姑娘和N头牛

    题目大意:取一种温度,让牛能产出最多的奶。已知每头牛最适合的温度和在这个温度区间上中下不同的产奶量。

    思路:先离散化,然后扫一遍所有的ai、bi,然后在0、ai、bi+1(一开始写成了bi,竟然过了75分。。。)处加上相应的值、在ai、bi+1、maxn减去相应的值,最后从头到尾扫一遍前缀和数组,最大值就是答案了。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int a[20001]={0},b[20001]={0},cc[80001]={0},sum[100000]={0},dd[100000]={0};
    int main()
    {
        freopen("milktemp.in","r",stdin);
        freopen("milktemp.out","w",stdout);
        
        int maxn=0,n,i,j,x,y,z,tot=0,size,ans=0;
        scanf("%d%d%d%d",&n,&x,&y,&z);
        for (i=1;i<=n;++i)
        {
            scanf("%d%d",&a[i],&b[i]);
            ++tot;cc[tot]=a[i];
            ++tot;cc[tot]=b[i];
        }
        sort(cc+1,cc+tot+1);
        size=unique(cc+1,cc+tot+1)-cc-1;
        for (i=1;i<=n;++i)
        {
            a[i]=upper_bound(cc+1,cc+size+1,a[i])-cc-1;
            b[i]=upper_bound(cc+1,cc+size+1,b[i])-cc-1;
            maxn=max(maxn,max(a[i],b[i]));
        }
        maxn+=2;
        for (i=1;i<=n;++i)
        {
            dd[0]+=x;
            dd[a[i]]-=x;dd[a[i]]+=y;
            dd[b[i]+1]-=y;dd[b[i]+1]+=z;
            dd[maxn]-=z;
        }
        ans=sum[0]=dd[0];
        for (i=1;i<=maxn;++i)
        {
            sum[i]=sum[i-1]+dd[i];
            ans=max(ans,sum[i]);
        }
        printf("%d
    ",ans);
        
        fclose(stdin);
        fclose(stdout);
    }
    View Code
  • 相关阅读:
    Atitit 趋势管理之道 attilax著
    Atitit 循环处理的新特性 for...else...
    Atitit 2017年的技术趋势与未来的大技术趋势
    atitit 用什么样的维度看问题.docx 如何了解 看待xxx
    atitit prj mnrs 项目中的几种经理角色.docx
    Atitit IT办公场所以及度假村以及网点以及租房点建设之道 attilax总结
    Atitit 工具选型的因素与方法 attilax总结
    Atitit.团队文化建设影响组织的的一些原理 法则 定理 效应 p826.v4
    Atiitt 管理方面的误区总结 attilax总结
    Atitit 未来趋势把控的书籍 attilax总结 v3
  • 原文地址:https://www.cnblogs.com/Rivendell/p/4141406.html
Copyright © 2011-2022 走看看