zoukankan      html  css  js  c++  java
  • 洛谷题解P1115 最大子段和 暨 P1714 切蛋糕

    P1115原题传送门

    P1714原题传送门

    ( ext{Solution - P1117})

    一道 DP 题目。

    • 状态的表示 : 令 (f[i]) 表示 以 (f[i]) 结尾的最大子段和。
    • 初始化 : (f[i] = 0)
    • 状态的转移 : (f[i] = max(f[i-1]+a[i],a[i]))

    但,对于状态的转移,我们可以发现数据范围

    对于 (100\%) 的数据,保证 (1 leq n leq 2 imes 10^5 , -10^4 leq a_i leq 10^4)

    明确标注了数列中可能存在负数,这一点在测试点 (2) 中也得到了完美的体现。(话说全是负数)

    当数列中存在负数时,(f[n]) 不一定是 (max)

    故,还需再在求完 (f[i]) 后求最大值并记录答案。

    ( ext{Code})

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int Maxn=2e5+10;
    inline void read(int &x){
    	int f=1;
    	char ch=getchar();
    	x=0;
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		x=(x<<3)+(x<<1)+ch-'0';
    		ch=getchar();
    	}
    	x*=f;
    } 
    int n;
    int a[Maxn];
    int dp[Maxn];
    inline int max(int a,int b){return a>b?a:b;}
    int main(){
    	int ans=1<<31;      //int max-> 1<<31-1,1<<31<0
    	read(n);
    	for(int i=1;i<=n;i++){
    		read(a[i]);
    		dp[i]=max(dp[i-1]+a[i],a[i]);
    		ans=max(dp[i],ans);
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    ( ext{Solution - P1117 & P1714})

    这两道题都可以用一种数据结构来解决。(双倍经验)
    这两道题都是最大区间的题
    所以可以维护一个前缀和单调递增的单调队列。
    基本和滑动窗口相似,只不过不需要维护一个 (p) 数组来记录队列中元素的值。

    ( ext{Code-P1714})( ext{P1115}) 代码相似,请读者自行修改)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int Maxn=5e5+10;
    inline void read(int &x){
    	int f=1;
    	char ch=getchar();
    	x=0;
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		x=(x<<3)+(x<<1)+(ch&15);
    		ch=getchar();
    	}
    	x*=f;
    }
    int n,m;
    int p;
    int sum[Maxn];
    int q[Maxn];
    int main(){
    	read(n);read(m);
    	for(int i=1;i<=n;i++){
    		read(p);
    		sum[i]=sum[i-1]+p;
    	}
    	int l=1,r=1;	//队列中默认有元素了,所以 r=1  
    	int ans=1<<31;	
    	for(int i=1;i<=n;i++){
    		while(l<=r&&q[l]<i-m) l++;	//过时出队 
    		ans=max(ans,sum[i]-sum[q[l]]);	//sum[i]-sum[q[l]] -> 通过维护前缀和数组求得当前区间和 
    		while(l<=r&&sum[i]<=sum[q[r]]) r--;	//维护单调递增 
    		q[++r]=i;
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    error: Microsoft Visual C++ 14.0 is required.
    pip安装其他包报错
    MapReduce
    机器学习算法使用
    结巴分词使用实例
    大数据——hbase
    机房收费系统系列一:运行时错误‘-2147217843(80040e4d)’;用户‘sa’登陆失败
    耿建玲视频总结
    学生信息管理系统系列三:验收时的改进
    学生信息管理系统系列二:常见问题
  • 原文地址:https://www.cnblogs.com/-pwl/p/13864882.html
Copyright © 2011-2022 走看看