精华内容
下载资源
问答
  • 要线段树资瓷区间max和询问区间和。 设要把$[L, R]$对mx取max。...然后我们假设找到了一个区间被$[L, R]$包含,那么如果这个区间的最大值小于mx,就直接修改,否则再递归进入他的子区间进行查找。 ...

    要线段树资瓷区间max和询问区间和。

    设要把$[L, R]$对mx取max。

    我们可以在线段树上二分出小于mx的区间然后变成区间修改了。

    具体实现是,维护区间最小值和区间最大值,我们递归进入一个区间,如果这个区间的最小值都大于mx的话就不用管这个区间了。

    然后我们假设找到了一个区间被$[L, R]$包含,那么如果这个区间的最大值小于mx,就直接修改,否则再递归进入他的子区间进行查找。

    void change(int l, int r, int o, int ql, int qr, int c)
    {
        if (mn[o] >= c) return ;
        if (l >= ql and r <= qr) 
        {
            if (mx[o] <= c) {
                mx[o] = mn[o] = lzy[o] = c;
                tr[o] = (r - l + 1) * c;
                return ;
            }
        }
        spread(o, l, r);//下放标记
        int mid = (l + r) >> 1;
        if (ql <= mid) change(l, mid, ls, ql, qr, c);
        if (qr > mid) change(mid + 1, r, rs, ql, qr, c);
        pushup(o);
    }

     

    转载于:https://www.cnblogs.com/BriMon/p/9864702.html

    展开全文
  • 求该区间内的最大子区间的和。 思路 暴力要搞到 O(n4)O(n^4)O(n4)。考虑一下降维和动归。 正常动归,要用到二维动态规划,可能会超时。 这里可以将每一列的前缀和算出来,即把每一列当作一个数,在确定好上下界之后...

    题面:To the Max

    题目大意

    给定一个整数 nn ,代表的是方形区间的边长,之后再输入所有格子内的数。
    求该区间内的最大子区间的和。

    思路

    暴力要搞到 O(n4)O(n^4)。考虑一下降维和动归。
    正常动归,要用到二维动态规划,可能会超时。

    这里可以将每一列的前缀和算出来,即把每一列当作一个数,在确定好上下界之后,就可以用一维动归来解决这个问题了。
    算法的时间复杂度就降到了 O(n3)O(n^3)

    贪心思想

    在做一维动归的时候,需要一些贪心思想。
    遍历到第 kk 个数时,如果前面 [1,k1][1,k-1] 个数的总和 last_sum0last\_sum\leq 0,那么说明我们可以将这第 kk 个数当作一个新的区间的开始。假设还加进 last_sumlast\_sum 的话,此时 last_sum+a[k]a[k]last\_sum+a[k]\leq a[k],则这个情况一定不是最优的,所以可以摒弃 last_sumlast\_sum

    代码

    #include <bits/stdc++.h>
    #define sc scanf
    #define pf printf
    using namespace std;
    const int N = 110;
    int n;
    int g[N][N];
    
    int main()
    {
        sc("%d", &n);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++) {
                sc("%d", &g[i][j]);
                //这里计算每一列的前缀和
                g[i][j] += g[i - 1][j];
            }
        int ans = INT_MIN;
        //用i确定上界
        for(int i = 1; i <= n; i++)
        	//用j确定下界
            for(int j = i; j <= n; j++)
            {
                int last = 0;//记录已经遍历过的总和。
                for(int k = 1; k <= n; k++) {
                	//如果last<=0,则让其等于0.
                	//g[j][k] - g[i-1][k] 计算的是上界 i 到下界 j的区间和
                	//子区间为 [i + x, i + k, j + x, j + k]
                	//其中 x 为last的起点,也可能为 k。
                    last = max(last, 0) + g[j][k] - g[i - 1][k];
                    ans = max(ans, last);
                }
            }
        pf("%d\n", ans);
        return 0;
    }
    
    展开全文
  • 思路:对于此类型的题目,可以从以下几个方面分析,  1....固有状态转移方程:dp[i][j]=max(dp[i-1][j-1],dp[i][j-1])+a[j];由于m的范围没有给出所以不可开dp[m][n]的数组。那么就需要有优化的方

    思路:对于此类型的题目,可以从以下几个方面分析,

       1.以当前的数为切入点,只有两种情况(1)当前的数单独的新放到一个区间.(2)将其放入和j-1同个区间。那么我们可以用dp[i][j]表示在前j个数划分了i个区间。固有状态转移方程:dp[i][j]=max(dp[i-1][j-1],dp[i][j-1])+a[j];由于m的范围没有给出所以不可开dp[m][n]的数组。那么就需要有优化的方案。类似于滚动数组的优化方式,可以开两个数组分别为pre[],now[]代表前一组和当前组的数字和情况。那么当加入一个新的数时,就需要判断一下是放入前一组还是当前组所得到的解最优。同时不断更新pre[]数组。(不知为啥用%I64dWA- -!)


    #include <iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define L int
    using namespace std;
    
    L now[1000100],pre[1000100],a[1000100];
    
    int main()
    {
        int n,m,i,j,k;
        while(~scanf("%d%d",&m,&n))
        {
            for(i=1; i<=n; i++)
            {
                scanf("%d",&a[i]);
                now[i]=pre[i]=0;
            }
            now[0]=pre[0]=0;
            L ma;
            for(i=1; i<=m; i++)
            {
                ma=-0x3f3f3f3f;
                for(j=i; j<=n; j++)
                {
                    now[j]=max(now[j-1],pre[j-1])+a[j];
                    pre[j-1]=ma;
                    if(now[j]>ma)
                    {
                        ma=now[j];
                    }
                }
               // pre[j-1]=ma;
            }
            printf("%d\n",ma);
        }
        return 0;
    }
    


    展开全文
  • Max Sum  Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 169481 A

    Max Sum

                                                                            Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

    Total Submission(s): 169481    Accepted Submission(s): 39557


    Problem Description
    Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
     

    Input
    The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
     

    Output
    For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
     

    Sample Input
    2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5
     

    Sample Output
    Case 1: 14 1 4 Case 2: 7 1 6
     

    Author
    Ignatius.L
     

    Recommend
    We have carefully selected several similar problems for you:  1176 1087 1069 2084 1058 
     
      
       解析:求连续子区间最大和。
                   用f【i】表示以第 i 个数字结尾的连续子区间的最大值,则 f【i】=max{f【i-1】+a【i】,a【i】},然后分情况处理一下起点、终点,并更新当前最优值即可。

    代码:
    #include<cstdio>
    #define inf 1000000000
    #define maxn 1000
    using namespace std;
    
    int ans,ans_l,ans_r;
    
    void work()
    {
      int i,j,k,n,x,sum,l,r;
      scanf("%d",&n);
      ans=-inf,sum=0,l=1,r=0;
      for(i=1;i<=n;i++)
        {
          scanf("%d",&x);
          if(sum<0)sum=x,l=r=i;
          else sum+=x,r=i;
          
    	  if(sum>ans)ans=sum,ans_l=l,ans_r=r;  
        }
      printf("%d %d %d\n",ans,ans_l,ans_r);  
    }
    
    int main()
    {
      freopen("1.in","r",stdin);
      int t,i;
      while(scanf("%d",&t)!=EOF)
        for(i=1;i<=t;i++)
          {
            printf("Case %d:\n",i);
            work();
            if(i<t)printf("\n");
          }
      return 0;
    }



    展开全文
  • 最大子区间

    千次阅读 2015-10-11 20:04:09
    #include "stdio.h" #include "stdlib.h" #include "math.h" ...#define N 100int MaxSum(int a[N], int n) //计算区间a[0:n-1]上最大子区间长度 { int i; int b = 0; int sum = 0; for(i=0; i
  • HDU 1231 最大连续序列 &&HDU 1003Max Sum (区间dp问题) 阅读:134 时间:2015-11-21 16:30 分享: C - 最大连续序列 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64...
  • 题目大意:求一个数列区间中最大的连续序列。  解题思路:这个题有三种做法,因为在学DP,所以只用了DP的做法,感觉DP很不好想,但想到了就会很简单。这个题的转移方程为:dp[i]=max(a[i],dp[i-1]+a[i]);即第i个...
  • 题意:价值 = 区间和 × 区间最小值,求数组的子区间的最大价值 (1)区间和---->前缀和 (2)O(n2) 枚举区间 —> O( n ) 枚举元素,根据当前元素查询相应区间和 对每个元素,维护他作为最小值的左右端点,...
  • http://acm.hdu.edu.cn/showproblem.php?pid=1003 Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 294367 Accepted Submission(s): 6989...
  • 求最大子区间

    2015-07-11 09:36:00
    int a[10],i,b[10],t; for(i=0;i<10;i++) scanf("%d",&a[i]);...b[i]=max(b[i-1]+a[i],a[i]); 再用选择排序法求数组b 的最大值 转载于:https://www.cnblogs.com/woyaocheng/p/4638054.htm...
  • dp[i]表示以in[i]结尾的最大子区间和,则dp[i]=max(0,dp[i-1])+in[i];然后比较dp[1...n]找到最大值 这道题的难点在于找到首尾的位置 1 #include<iostream> 2 #include<string.h> 3 #include<...
  • 维护2个双端队列A,B。...窗口扩张后,当前窗口的max只会比之前窗口的max大,min比之前窗口的min小。 那这时就可以求出窗口左边以第一位置开始的valid窗口的个数,就是窗口的宽度 接着左边从第一位移到第二
  • Problem Description ... Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1...
  • 题意:n个数,分成m片区间Max为m片区间中的最大区间区间元素和最大),求Max的最小值 思路:二分枚举一个最大值,每次判断从前往后是否可以分成m份(如果分成小于m份也可以把一个区间拆成多个区间,所以&...
  • 最大连续子区间(和) ans = lst = 0; for(i = 0; i < n; ++i){ lst = max(0, lst) + a[i]; //lst = max(lst+a[i], a[i]); ans = max(ans, lst); }
  • 最大值子区间和的一维二维问题

    千次阅读 2015-02-15 22:05:07
    题目大意:给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该序列的和最大,其中,1 思路:m是元素总个数,sum是第一个元素,将当前的第一个元素作为最大值max,之后依次输入,检查sum 代码...
  • 不熟练的原因是理解的不够深…… ...#define MAX(a, b) ((a)>(b)?(a):(b)) int num[100] = {-1, 2, 5, -4, 3, 0, -1, 3, 6, -10}; int n = 10; int func1(){ int i; int max = 0x80000000, sum = 0;
  • 问题:问题1 的代码实现:#coding:utf-8#py2.7def findmaxsubstr(nums):bufs={}for i,num in enumerate(nums):if i==0:bufs[i]=numelse:bufs[i]=bufs[i-1]+num if...=0 else numprint bufsb=max([(bufs[i],i) for i ...
  • 给定一个序列a[1],a[2],a[3]…a[n],你的工作是计算序列的最大和。例如,给定(6,-1,5,4,-7),这个序列中的最大和是6 +(-1)+ 5 + 4 = 14。 输入 输入的第一行包含一个整数T(1<=T<=20),这意味着测试用例...
  • dp(i+1)=max(num[i+1], num[i+1]+dp(i)); dpi表示以第i元素结尾的最大区间和。 #include<iostream> using namespace std; int main() { int n; cin>>n; int* a=new int[n+1]; a[0]=0; for(int ...
  • #include #include //小白窝不讲题hhh int num=1; int start,end; int dp[1000][1000];...int max(int m,int n) { if(m>=n) return m; else return n; } int SQRT(int n) //求2的n次方 { int t=n%2;
  • 题目一描述: 给定一个整数数组 nums ,找到一个具有最大和的连续数组(...动态规划: dp[i]=Math.max(dp[i-1]+nums[i],nums[i]) 贪心法: 分治法: 最优解:动态规划 代码: /** * @param {number[]} nums * @re
  • 求一个数组的连续数组的最大值(以及区间) package suanfa.impover; /** * 求一个数组的连续数组的最大值(以及区间) */ import java.util.Arrays; public class SubArrayMaxSum { // 暴力破解,O(n2)...
  • 区间最大连续字段 线段树多维护三个值:当前区间从左端开始最大连续和cl,从右端开始最大连续和...m等于max(左子区间m,右子区间m,左子区间cr+右子区间cl) 查询时返回区间段并不断合并。 struct node { int s,c...
  • 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003本题使用递归分治求解最大序列问题。# include # include<malloc.h>typedef struct{ int left;... int maxsum;//区间最大和 }Sum;Sum m
  • 区间DP

    2020-08-09 13:55:35
    求一段区间的最优解,该区间的最优解可以由其子区间的最优解推导而来,类似分治思想。 令状态f(i,j)表示将下标位置 i 到 j 的所有元素合并能获得的价值的最大值,那么 f(i,j) = max{f(i,k) + f(k+1, j) + cost}, k∈...
  • 方程是:f[i][j]=max(f[i][j],f[i-1][k]+a[i][j-k]);我们要去枚举每一个i和j,因此用双重循环来解决,k表示第i个公司取的不取机器数,即1~i-1个公司取的机器数;f[i-1][k]表示前i-1个公司取k台机器的最大值,a[i][j-...
  • 题目翻译:给出N个数字,Q个操作,如果输入操作类型是a,则【L,R】...一个区间,其两个子区间依据边界值对 两个区间进行合并。 Max数组维护任意一个区间的最长连续子序列长度。 lnum数组保存一个区间左边界的数

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 468
精华内容 187
关键字:

max子区间