1. 程式人生 > 其它 >codeforces699 div2 ABC | cf699 div2 abc | 貪心,貪心,還是貪心

codeforces699 div2 ABC | cf699 div2 abc | 貪心,貪心,還是貪心

今日的cf題解,與總結,又因為本地的程式總被刪掉,所以把除錯過程也加上,作為日後回顧。

無趣的刷題才是日常,本文遵循的方法論在這篇文章中。https://www.cnblogs.com/cosmowind/p/15982590.html

 

 

A

1、概括題面:在座標軸上,機器人初始位置為(0,0),輸入一串指令UDLR,分別表示上下左右走一格。問,每個指令可以接受或執行,機器人能否走到(x,y)?

2、分析過程:
①關鍵詞:貪心
②思路:只走能接近目標的指令,其餘忽略。
③實現:統計各個指令的個數,最後判斷需要的方向上的指令數是否能達到目標。
④複雜度:o(n)

3、貼個程式碼:

#include<iostream>
#include
<stdio.h> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<map> #include<vector> using namespace std; #define _for(i,a,b) for(int i=(a);i<=(b);i++) #define _rp(i,b,a) for(int i=(b);i>=(a);i--) //#define int long long #define
close std::ios::sync_with_stdio(0) typedef long long ll; const int N=2e5+7; int t,a,b; string s; signed main(){ cin>>t; while(t--){ cin>>a>>b; cin>>s; _for(i,0,s.length()-1){ if(a>0){ if(s[i]=='R')a--; }
else if(a<0){ if(s[i]=='L')a++; } if(b>0){ if(s[i]=='U')b--; }else if(b<0){ if(s[i]=='D')b++; } } if(!a&&!b)cout<<"YES\n";else cout<<"NO\n"; } }

 

 

B(如果不是因為寫部落格,這題我再也不想看)

1、概括題面:n座山,分別有高度a[i]。給定k顆滾石,每顆滾石從第一座山開始向右滾,如果下一座山不高於自己,就滾到下一座山,最後滾到世界盡頭;否則留在這座山,使之高度+1。問,第k顆滾石會停在哪?

2、分析過程:
①關鍵詞:貪心、分類討論
②思路:根據題意,在遇到一座高山時,需要把它之前的所有矮山都填到與自己同高才能通過。所以維護一個單調棧,每遇到一座比當前高的山,就把棧內所有比它低的山都拿出來填,如果k用完了,說明最後的滾石就在當前的高山以前(不包括它),棧內最頂部的元素之後(包括它),具體演算法是用left_k對兩者距離取模,具體實現見程式碼。如果遍歷完所有山k>0,則輸出-1。
③重要細節:當對棧裡的最小元素進行填山時,應該注意到不能直接把這座山填到和高山一樣的高度,因為,如果當棧內最小元素達到次小元素的大小時,同時填山的區間就會擴大,此時將最小元素退棧,用次小元素繼續執行。
④複雜度:o(n)

3、貼個程式碼:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<=(b);i++)
#define _rp(i,b,a) for(int i=(b);i>=(a);i--)
//#define int long long
#define close std::ios::sync_with_stdio(0)

typedef long long ll;
const int N=2e5+7;

int t,a[N],b,s[N],bord,n,k,flag,ans,calc;
vector<int> zh;
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>k;
        s[0]=0;
        a[0]=N;
        _for(i,1,n)cin>>a[i],s[i]=s[i-1]+a[i];
        zh.clear();
        zh.push_back(0);
        zh.push_back(1);
        flag=0;ans=-1;
        _for(i,2,n){
            while(zh.size()>0&&a[zh.back()]<a[i]){
                bord=zh.back();
                if(zh.size()>1&&a[zh.back()-1]<a[i]){
                    calc=((i-bord)*a[zh.back()-1])-(s[i-1]-s[bord-1]);
                    if(calc<k){
                        k-=calc;
                        _for(j,bord,i-1)a[j]=a[zh.back()-1];
                        _for(j,1,n)s[j]=s[j-1]+a[j];
                        //cout<<k<<" "<<bord<<" "<<a[2]<<endl;
                    }else{
                        //cout<<"there\n";
                        ans=i-1-(k-1)%(i-bord);
                        //cout<<bord<<" "<<i<<" "<<a[bord]<<" "<<a[i]<<" "<<calc<<" "<<ans<<endl;
                        flag=1;
                        break;
                    }
                    zh.pop_back();
                }else{
                    calc=((i-bord)*a[i])-(s[i-1]-s[bord-1]);
                    //cout<<bord<<" "<<i<<" "<<a[bord]<<" "<<a[i]<<" "<<calc<<" "<<ans<<endl;
                    if(calc<k){
                        k-=calc;
                        _for(j,bord,i-1)a[j]=a[i];
                        _for(j,1,n)s[j]=s[j-1]+a[j];
                        //cout<<k<<" "<<bord<<" "<<a[2]<<endl;
                    }else{
                        //cout<<"there\n";
                        ans=i-1-(k-1)%(i-bord);
                        //cout<<bord<<" "<<i<<" "<<a[bord]<<" "<<a[i]<<" "<<calc<<" "<<ans<<endl;
                        flag=1;
                        break;
                    }
                }
            }
            if(a[i]<a[zh.back()])zh.push_back(i);
            //zh.push_back(i);
            if(flag)break;
            /*
            cout<<"look "<<zh.size()<<" "<<zh.back()<<endl;
            _for(j,0,zh.size()-1)cout<<zh[j]<<" ";cout<<endl;
            _for(j,0,zh.size()-1)cout<<a[zh[j]]<<" ";cout<<endl;
            */
        }
        if(flag)cout<<ans<<endl;else cout<<-1<<endl;
    }
    
    
}
/*

1
12 172
60 7 60 49 5 80 1 78 41 9 57 65

25 2114
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100



*/

 

 

C

1、概括題面:n個柵欄,原有顏色a[i],目標顏色b[i],先後請來m個粉刷匠,只能給1個柵欄上色為c[i]。問,能否達到目標?粉刷匠分別給哪個柵欄上色?

2、分析過程:產生做法的思路過程,總體說解題演算法的關鍵詞,某某資料結構,dp狀態之類的。對一些重要的細節,討論的過程進行具體闡述。最後分析複雜度。
①關鍵詞:貪心(除了貪心不知道怎麼描述)
②思路:首先倒著列舉粉刷匠,因為越靠後的粉刷匠越不會被其它顏色遮蓋。對於每個粉刷匠,做三個判斷:(1)對應的顏色還有沒有需要塗的?qu[c[i]]>0?【進行上色任務】(2)目標顏色b[i]中是否有c[i]這個顏色?【無需該色,找個不做負面影響的地方】(3)該粉刷匠是否為倒數第一個粉刷匠?如果是最後的粉刷匠,又沒有對目標做貢獻,也沒有相同顏色存放自己,那就只能破壞計劃,直接輸出 NO。
③重要細節:為執行以上功能,我們需要預處理出相應的陣列。qu[i]表示顏色i需要用在第qu[i]個柵欄上;last[i]表示與位置i上顏色相同且也需要上色的上一個位置在哪,若沒有則為0;
④複雜度:o(n)

3、貼個程式碼:程式碼中還有其它的優化,實際上不要也罷。比如,統計粉刷匠能提供的顏色數以及某種顏色需要的個數,若前者較小,則失敗。

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<=(b);i++)
#define _rp(i,b,a) for(int i=(b);i>=(a);i--)
//#define int long long
#define close std::ios::sync_with_stdio(0)
#define mst(f,a) memset(f,a,sizeof(f));
#define die cout<<"NO\n";return
typedef long long ll;
const int N=1e5+7;

int n,m,t,a[N],b[N],c[N],qu[N],last[N],cnt_lai[N],cnt_que[N],wri[N],po[N];
string s;

void solve(){
    cin>>n>>m;
    mst(last,0);
    mst(qu,0);
    mst(cnt_lai,0);
    mst(cnt_que,0);
    mst(wri,0);
    mst(po,0);
    _for(i,1,n)cin>>a[i];
    _for(i,1,n)cin>>b[i];
    _for(i,1,m)cin>>c[i],cnt_lai[c[i]]++;
    _for(i,1,n){
        if(a[i]!=b[i]){
            cnt_que[b[i]]++;
            //if(qu[b[i]]){
                last[i]=qu[b[i]];
                qu[b[i]]=i;
                //cout<<b[i]<<" "<<a[i]<<" "<<i<<" "<<qu[b[i]]<<endl;
            //}
            if(cnt_lai[b[i]]<cnt_que[b[i]]){
                die;
            }
        }
        po[b[i]]=i;
    }
    //cout<<"there\n";
    _rp(i,m,1){
        //cout<<" "<<i<<" "<<t<<endl;
        if(qu[c[i]]>0){
            wri[i]=qu[c[i]];
            qu[c[i]]=last[qu[c[i]]];
            //cout<<"__ "<<i<<" "<<t<<" "<<wri[i]<<" "<<qu[c[i]]<<endl;
        }else if(po[c[i]]>0){
            wri[i]=po[c[i]];
            //cout<<"++ "<<i<<" "<<t<<endl;
        }else if(i<m){
            wri[i]=wri[m];
            //cout<<"33 "<<i<<" "<<t<<endl;
        }else{
            die;
        }
    }
    _for(i,1,n){
        if(qu[i]){
            die;
        }
    }
    cout<<"YES\n";
    _for(i,1,m){
        cout<<wri[i]<<" ";
        a[wri[i]]=c[i];
    }
    cout<<endl;/*
    _for(i,1,n){
        cout<<a[i]<<" ";
    }
    cout<<endl;
    */
}

signed main(){
    close;
    cin>>t;
    while(t--){
        solve();
    }
}
/*
1
27 24
21 18 18 23 17 8 7 21 12 10 3 13 5 16 3 17 7 27 20 18 2 5 3 26 22 24 2
15 9 18 23 17 8 7 21 12 10 3 13 5 16 3 17 13 27 22 18 2 5 3 25 22 24 2
22 9 27 15 7 20 7 9 6 27 11 1 11 23 12 25 19 22 9 15 11 13 5 9




*/