2018牛客暑假多校二 D(贪心)
生活随笔
收集整理的這篇文章主要介紹了
2018牛客暑假多校二 D(贪心)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述:
? ? 你要按照順序以此經過n個商店,每到達一個商店你可以購買一件物品,也可以出售你手中的商品。 同一時刻你手上最多拿一件商品。在第i個商店購買和出售的代價都是a[i]。?
? ? 問你經過完n個商店后的最大收益。 同時,在最大化收益的前提下,求最小的交易次數。
題目分析:
? ? 不難發現,要想使得利益最大,我們肯定是要在一個單調區域中的最小值中購入,再從該單調區域的最大值時轉出。倘若發現了這個事實,則我們就可以將題目轉化為一個判斷兩個單調區間的拐點為極大值還是極小值。(具體判斷方法就是將某個點與之前一個和后一個點比較)
? ? 倘若我們發現此時位于極小值,則我們需要更新價格最小cur。而當我們發現此時位置處于極大值,則更新最大利益sum=當前價格-最小價格,并將最小價格賦為-1代表沒有最便宜的物品。
? ? 而當我們取到最后一個點時,我們需要特判一下,如果當前是極大值點亦或者 當前不是極大值點,但拿了一個物品,則進行更新。
? ? 值得留意的是,如果遇到連續相同的價格的時候(如數列[1,2,2,3,4]中的[2,2]),因為此時這些連續的價格對結果沒有影響(甚至會阻礙我們的判斷)因此我們考慮將這些連續相同的點去重。
#include <bits/stdc++.h> #define maxn 100005 using namespace std; typedef long long ll; ll a[maxn]; ll tmp[maxn]; int main() {int t;scanf("%d",&t);while(t--){int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%lld",&tmp[i]);}int cnt=0;for(int i=1;i<=n;i++){//去重if(i==1){a[++cnt]=tmp[i];continue;}if(tmp[i]!=tmp[i-1]){a[++cnt]=tmp[i];}}ll cur=-1;ll sum=0,num=0;for(int i=1;i<=cnt;i++){if(i==1){if(a[i]<a[i+1]) cur=a[i];continue;}if(i==n){if(a[i]>a[i-1]) sum+=a[i]-cur,num+=2;else if(cur>=0) sum+=a[i]-cur,num+=2;continue;}if(a[i]>a[i-1]&&a[i]>a[i+1]){//當前處于極大值sum+=a[i]-cur,num+=2;cur=-1;}else if(a[i]<a[i-1]&&a[i]<a[i+1]){//當前處于極小值cur=a[i];}}cout<<sum<<" "<<num<<endl;} }?
轉載于:https://www.cnblogs.com/Chen-Jr/p/11007265.html
總結
以上是生活随笔為你收集整理的2018牛客暑假多校二 D(贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java(IO)读写文件乱码转换UTF-
- 下一篇: C语言中文件定位函数总结