Codeforces Round #622 (Div. 2)題解(部分)

鏈接:https://codeforces.com/contest/1313
來源:codeforces

A. Fast Food Restaurant(貪心)

  思路:直接貪心的取,對三個數進行排序,貪心匹配

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+10;
int a[maxn];

int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&a[1],&a[2],&a[3]);
        sort(a+1,a+4);
        if(a[3]==0) puts("0");
        else if(a[2]==0) puts("1");
        else if(a[1]==0){
            int cnt=2;
            a[2]--; a[3]--;
            if(a[2]) cnt++;
            printf("%d\n",cnt);
        }else{
            int cnt=3;
            a[1]--; a[2]--; a[3]--;
            if(a[1]&&a[3]) { a[3]--;a[1]--;cnt++; }
            if(a[2]&&a[3]) { a[3]--;a[2]--;cnt++; }
            if(a[1]&&a[2]) { a[1]--;a[2]--;cnt++; }
            if(a[1]&&a[2]&&a[3]) cnt++;
            printf("%d\n",cnt);
        }
    }
    return 0;
}

B. Different Rules(思維)

  思路: minmin: (l+r)n(l+r)-n   [1,l+rn][1,l+r-n] 這個區間的數字無論和誰組合都會小於等於 l+rl+r,所以這些數字無論如何組合都不會大於 [l+r][l+r]   maxmax:我們考慮 11 和什麼數字相加的時候等於 l+rl+r,那麼這個區間以內的數都可以互相結合小於等於 l+rl+r 此區間就是 [1,l+r1][1, l+r-1]

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

int main(){
    int T; scanf("%d",&T);
    while(T--){
        ll n,l,r;
        scanf("%lld%lld%lld",&n,&l,&r);
        printf("%lld %lld\n",min(max((l+r)-n+1,1ll),n),min(l+r-1,n));
    }
    return 0;
}

C1. Skyscrapers (easy version)(枚舉)

  思路:我們枚舉每一個峯值,那麼他左邊的數字一定都是遞減的,右邊的數字一定都是遞增的,直接枚舉判斷即可。注意數據範圍:long long

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=1e3+10;
int a[maxn],b[maxn];

int main(){
    int n; scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    ll MMax=INT_MIN; int inx=-1;
    for(int i=1;i<=n;i++){
        int Max=a[i]; ll sum=a[i];
        for(int j=i-1;j>=1;j--) { Max=min(a[j],Max); b[i]=Max; sum+=(ll)b[i]; }
        Max=a[i];
        for(int j=i+1;j<=n;j++) { Max=min(a[j],Max); b[i]=Max; sum+=(ll)b[i]; }
        // for(int j=1;j<=n;j++) cout<<b[i]<<" ";
        if(MMax<sum) { MMax=sum;inx=i; }
    }
    int Max=a[inx];
    for(int i=inx;i>=1;i--) { Max=min(a[i],Max); a[i]=Max; }
    Max=a[inx];
    for(int i=inx;i<=n;i++) { Max=min(a[i],Max); a[i]=Max; }
    for(int i=1;i<=n;i++) printf("%d%c",a[i],i==n?'\n':' ');
    return 0;
}

C2. Skyscrapers (hard version)(單調棧)

  思路:此題目相對於上面一題只是數據範圍發生了變化,在找峯值的時候,對於左右兩邊的和我們可以進行優化,我們找到每個數字左側的小於等於它本身的第一個數,右側小於等於它本身的最後一個數。(這個過程可以通過單調棧來實現),接下來我們就可以計算出來每一點爲峯值的時候它左右兩側的和(兩邊都是遞減的)。然後遍歷數組找到和最大的那個點。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=5e5+10;
int a[maxn];

stack<int>stk;
int l[maxn],r[maxn];
ll L[maxn],R[maxn];

int main(){
    int n; scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        while(stk.size()&&a[stk.top()]>a[i]) stk.pop();
        if(stk.empty()) l[i]=0;
        else l[i]=stk.top();
        stk.push(i);
    }
    while(stk.size()) stk.pop();
    for(int i=n;i>=1;i--){
        while(stk.size()&&a[stk.top()]>a[i]) stk.pop();
        if(stk.empty()) r[i]=n+1;
        else r[i]=stk.top();
        stk.push(i);
    }
    //for(int i=1;i<=n;i++) cout<<l[i]<<" "<<r[i]<<endl;
    for(int i=1;i<=n;i++) L[i]=L[l[i]]+1ll*(i-l[i])*a[i];
    for(int i=n;i>=1;i--) R[i]=R[r[i]]+1ll*(r[i]-i)*a[i];
    //for(int i=1;i<=n;i++) cout<<L[i]<<" "<<R[i]<<endl;
    ll MaxUp=INT_MIN; int inx=-1;
    for(int i=1;i<=n;i++){
        ll res=L[i]+R[i]-(ll)a[i];
        if(MaxUp<res){
            MaxUp=res;
            inx=i;
        }
    }
    int MaxPre=a[inx],MaxSuf=a[inx];
    for(int i=inx;i>=1;i--) { MaxPre=min(a[i],MaxPre); a[i]=MaxPre; }
    for(int i=inx;i<=n;i++) { MaxSuf=min(a[i],MaxSuf); a[i]=MaxSuf; }
    for(int i=1;i<=n;i++) printf("%d%c",a[i],i==n?'\n':' ');
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章