您的位置:首页 > 其它

2017 济南综合班 Day 1

2017-08-01 09:05 417 查看
[b]送分题(songfen)[/b]

Time Limit:1000ms Memory Limit:128MB

题目描述

LYK喜欢干一些有挑战的事,比如说求区间最大子段和。它知道这个题目有O(n)的做法。于是它想加强一下。

也就是说,LYK一开始有n个数,第i个数字是ai,它找来了一个新的数字P,并想将这n个数字中恰好一个数字替换成P。要求替换后的最大子段和尽可能大。

LYK知道这个题目仍然很简单,于是就扔给大家来送分啦~

注:最大子段和是指在n个数中选择一段区间[L,R](L<=R)使得这段区间对应的数字之和最大。

输入格式(songfen.in)

第一行两个数n,P。

接下来一行n个数ai。

输出格式(songfen.out)

一个数表示答案。

输入样例

5 3

-1 1 -10 1 -1

输出样例

5

样例解释

将第三个数变成3后最大子段和为[2,4]。

数据范围

对于30%的数据n<=100。

对于另外30%的数据ai,P>=0。

对于100%的数据n<=1000,-1000<=ai,P<=1000。

Note:提前AK的同学可以想一想O(n)的做法。

枚举改哪个,再做O(n)的最大子段和。总复杂度:O(n²)

O(n)做法用栈,不会。。。。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1001
using namespace std;
int n,k,maxn=-2e9,minn=2e9;
int a
,dp[N+4];
bool check(int mid)
{
dp[0]=0;
for(int i=1;i<=n;i++)
{
dp[i]=n+4;
for(int j=i-1;j>=0;j--)
if(!j || mid*(i-j)>=abs(a[i]-a[j])) dp[i]=min(dp[i],dp[j]+i-j-1);
}
for(int i=1;i<=n;i++)
if(dp[i]+n-i<=k) return true;
return false;
}
int main()
{
freopen("fangak.in","r",stdin);
freopen("fangak.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),maxn=max(maxn,a[i]),minn=min(minn,a[i]);
int l=0,r=maxn-minn,mid,ans;
while(l<=r)
{
mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d",ans);
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: