习题 8-18 UVA - 1619 Feel Good 感觉不错 (容斥定理)
2016-05-20 21:46
405 查看
大体题意:
给你一个长度为n (n <= 100000)的正整数序列ai,求出一段连续子序列a1,,ar 使得 (a1 + a2+ a3 +... ar) * min (a1,a2,a3,,,,ar)尽量大 如果多解任意输出一个!
思路:
思路是比较清晰的,就是有坑:
用sum[i]表示 1 ...i 的和,l[i],r[i],分别表示以第 i 个数字为最小值所能扩展的最左端和最右端!
最后遍历i 更新ans
ll ans = a[i] * (sum[r[i]] - sum[l[i]-1]);
取个最大值即可!
求l 和r 数组还不能暴力求,这样会超时。
for (int i = 1; i <= n; ++i)
while(a[l[i]-1] >= a[i])l[i] = l[l[i]-1];
这样求得话 因为遍历到i 时,l[i] 肯定等于i 的,所以当i的位置前一个数值大于等于 第i 个数值时,第i个数值就应该扩展到 第i个数 前一个位置的数 所能扩展到的位置!
r数组 同理。
最后是更新ans
记录下标时 pl 记录l pr 记录r 他们必须初始化,因为刚上来可能是0嘛! 数据问题!
然后MAX 初始化为0 在与ans 不断比较就可以了
给你一个长度为n (n <= 100000)的正整数序列ai,求出一段连续子序列a1,,ar 使得 (a1 + a2+ a3 +... ar) * min (a1,a2,a3,,,,ar)尽量大 如果多解任意输出一个!
思路:
思路是比较清晰的,就是有坑:
用sum[i]表示 1 ...i 的和,l[i],r[i],分别表示以第 i 个数字为最小值所能扩展的最左端和最右端!
最后遍历i 更新ans
ll ans = a[i] * (sum[r[i]] - sum[l[i]-1]);
取个最大值即可!
求l 和r 数组还不能暴力求,这样会超时。
for (int i = 1; i <= n; ++i)
while(a[l[i]-1] >= a[i])l[i] = l[l[i]-1];
这样求得话 因为遍历到i 时,l[i] 肯定等于i 的,所以当i的位置前一个数值大于等于 第i 个数值时,第i个数值就应该扩展到 第i个数 前一个位置的数 所能扩展到的位置!
r数组 同理。
最后是更新ans
记录下标时 pl 记录l pr 记录r 他们必须初始化,因为刚上来可能是0嘛! 数据问题!
然后MAX 初始化为0 在与ans 不断比较就可以了
#include<cstdio> #include<cstring> #include<algorithm> #define fin freopen("cin.txt","r",stdin); #define fout freopen("out.txt","w",stdout); using namespace std; typedef long long ll; const int INF = 1e9+5; const int maxn = 100000 + 10; int n,a[maxn]; ll sum[maxn]; int pl,pr,cnt; int l[maxn],r[maxn]; int main(){ // fin; while(scanf("%d",&n) == 1){ for (int i = 1; i <= n; ++i){ scanf("%d",&a[i]); sum[i] = sum[i-1] + a[i]; l[i] = r[i] = i; } a[0] = -INF; a[n+1] = -INF; 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]; // printf("start\n"); // for (int i = 1; i <= n; ++i)printf("%d ",a[i]); // printf("\n"); // for (int i = 1; i <= n; ++i)printf("%d ",l[i]); // printf("\n=\n"); // for (int i = 1; i <= n; ++i)printf("%d ",r[i]); // printf("\n"); ll MAX = 0; pl = pr = 1; for (int i = 1; i <= n; ++i){ ll ans = a[i] * (sum[r[i]] - sum[l[i]-1]); if (ans > MAX){ // printf("%lld\n",ans); MAX = ans; pl = l[i]; pr = r[i]; } } if (cnt++)printf("\n"); printf("%lld\n%d %d\n",MAX,pl,pr); } return 0; }
相关文章推荐
- mac 搭建react-native环境,无法run-android的问题
- Javascript基础知识盲点总结——继承
- CSS3边框温故
- POJ 1274 - The Perfect Stall
- 关于js里undefined的重写问题
- 关于html/css的内容第二弹
- json的反序列化
- String和StringBuffer
- 文件和目录属性
- 1.从Jquery 到 Reactjs 转变 遇到的十大神坑
- JSON
- React Native的Navigator详解
- Node-Webkit打包
- 在node中使用babel6的一些简单分享
- DeCAF: A Deep Convolutional Activation Featurefor Generic Visual Recognition阅读
- JavaScript之表格修改
- 用纯css改变下拉列表select框的默认样式
- JDBC中的setFetchSize()
- javascript将字符串转换为日期并比较大小
- caffe 入门实例3 fine-turning