UVA 1619 Feel Good
2017-09-01 23:36
337 查看
题意:给出一个长度为n的正整数序列ai,求出一段连续子序列al,...,ar,使得(al+...+ar)*min{al,...,ar}尽量大
解题思路:提前处理好sum[i]也就是前i项和,那么再求连续子序列的和就好求了。这道题的关键是处理以ai作为最小值的统治域,就是说在L[i]到R[i]这个区间里ai是最小值,处理L[i]和R[i]时可以用一种类似于dp的方法,首先将L[i]和R[i]都初始化为i,然后从前往后遍历找L[i],再从后往前遍历找R[i],举个例子:6 5 4 3 2,3的左端点是L[1]=6,然后再看2,因为2比3小,所以可以直接继承3的左端点,比3大的数一定比2大,就不用再重复着求了,这个方法很巧妙。注意要将a[i]数组初始化为-1,不然会超时,因为在找左右端点时会出现问题
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=100000+10;
int n;
int a[maxn],L[maxn],R[maxn];
ll sum[maxn];
int main()
{
int cas=0;
while(scanf("%d",&n)==1)
{
memset(a,-1,sizeof(a));
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
L[i]=i;
R[i]=i;
}
for(int i=1;i<=n;i++)
{
while(a[L[i]-1]>=a[i])
{
L[i]=L[L[i]-1];
}
}
for(int i=n;i>=1;i--)
{
while(a[R[i]+1]>=a[i])
{
R[i]=R[R[i]+1];
}
}
ll ans=0;
int l=1,r=1;
for(int i=1;i<=n;i++)
{
ll ans2=a[i]*(sum[R[i]]-sum[L[i]-1]);
if(ans2>ans)
{
ans=ans2;
l=L[i];
r=R[i];
}
}
if(cas)printf("\n");
cas++;
printf("%lld\n",ans);
printf("%d %d\n",l,r);
}
return 0;
}
解题思路:提前处理好sum[i]也就是前i项和,那么再求连续子序列的和就好求了。这道题的关键是处理以ai作为最小值的统治域,就是说在L[i]到R[i]这个区间里ai是最小值,处理L[i]和R[i]时可以用一种类似于dp的方法,首先将L[i]和R[i]都初始化为i,然后从前往后遍历找L[i],再从后往前遍历找R[i],举个例子:6 5 4 3 2,3的左端点是L[1]=6,然后再看2,因为2比3小,所以可以直接继承3的左端点,比3大的数一定比2大,就不用再重复着求了,这个方法很巧妙。注意要将a[i]数组初始化为-1,不然会超时,因为在找左右端点时会出现问题
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=100000+10;
int n;
int a[maxn],L[maxn],R[maxn];
ll sum[maxn];
int main()
{
int cas=0;
while(scanf("%d",&n)==1)
{
memset(a,-1,sizeof(a));
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
L[i]=i;
R[i]=i;
}
for(int i=1;i<=n;i++)
{
while(a[L[i]-1]>=a[i])
{
L[i]=L[L[i]-1];
}
}
for(int i=n;i>=1;i--)
{
while(a[R[i]+1]>=a[i])
{
R[i]=R[R[i]+1];
}
}
ll ans=0;
int l=1,r=1;
for(int i=1;i<=n;i++)
{
ll ans2=a[i]*(sum[R[i]]-sum[L[i]-1]);
if(ans2>ans)
{
ans=ans2;
l=L[i];
r=R[i];
}
}
if(cas)printf("\n");
cas++;
printf("%lld\n",ans);
printf("%d %d\n",l,r);
}
return 0;
}
相关文章推荐
- UVA - 1619 Feel Good (延伸+滚动窗口) 蜜汁wa
- UVA 1619 Feel Good(DP)
- UVA - 1619 Feel Good(高效算法:滑动窗口)
- UVA-1619 Feel Good (单调队列)
- UVA 1619 - Feel Good(dp 求区间最小值 附加RMQ)(区间最小值优化)
- uva 1619 - Feel Good || poj 2796 单调栈
- UVA 1619 Feel Good(DP)
- 习题 8-18 UVA - 1619 Feel Good 感觉不错 (容斥定理)
- [UVa 1619]Feel Good
- 【UVA】1619-Feel Good(数据结构-栈)
- UVA 1619 Feel Good 感觉不错 迭代法 (2005 NE)
- UVA 1619 Feel Good 感觉不错 (扫描法)
- Feel Good UVA - 1619
- [UVA1619]Feel Good[DP]
- UVA - 1619 Feel Good 标记+枚举
- UVA1619 栈维护递增序列
- UVA1619 感觉不错
- UVa - 1619 - Feel Good
- UVa - 1619 - Feel Good
- uva 1619 - Feel Good