1. 程式人生 > 實用技巧 >【Codeforces Round #650 (Div. 3) D】Task On The Board

【Codeforces Round #650 (Div. 3) D】Task On The Board

題目連結

連結

翻譯

\(s\) 刪掉 \(|s|-m\) 個字元之後,剩下的 \(m\) 個字元任意排序得到 \(t\)。根據 \(t\) 上每個字元的字典序的大小關係生成了一個序列 \(b\)

現在告訴你 \(s\) 以及 \(m\)\(b\) 讓你輸出某個可能的 \(t\)

題解

\(trick\) 就是每次找到 \(b\) 的值為 \(0\) 的位置,其他不為 \(0\) 的位置,肯定要減去和它的下標的差的絕對值(為 \(0\) 說明對應位置上的字母的字典序最大)

重複上述過程。每次有幾個 \(0\) 就說明有對應數目的字典序的字母。

那麼從'z'到'a'檢視每個字母在 \(s\)

中出現的次數,對照通過 \(b\) 求出來的 \(t\) 中第一大的字典序,第二大的字典序個數。只要原字串中對應字母 \(key\) 的出現次數

大於等於第 \(i\) 大的字典序的字母個數,那麼就貪心地認為這個第 \(i\) 大的字母就是 \(key\)

程式碼

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

const int N = 50;
//第 i 大的字元的下標
vector<int> v[N+10];
//已經訪問過的位置
bool vis[N+10];
string s;
int n,m;
int b[N+10];

int main(){
    // freopen("C://1.cppSourceProgram//rush.txt","r",stdin);
    ios::sync_with_stdio(0),cin.tie(0);
    //step10多組資料
    int T;
    cin >> T;
    while (T--){
        memset(vis,0,sizeof(vis));
        //step1 只考慮一組資料
        //step2 輸入資料
        cin >> s;
        cin >> m;
        for (int i = 1;i <= m; i++){
            cin >> b[i];
        }
        n = s.length();
        //step3 未訪問的位置個數 cnt
        int cnt = m;
        //step4 迴圈找最大值
        int _rank = 0;
        while (cnt > 0){
            //step5 第 rank 大的
            _rank++;
            v[_rank].clear();
            //step6 找 0 的位置放到v當中
            for (int i = 1;i <= m; i++){
                if (b[i] == 0 && !vis[i]){
                    v[_rank].push_back(i);
                    vis[i] = true;
                    cnt--;
                }
            }
            //step7 把其他不為 0 的減去和這些值的位置差絕對值
            for (int i:v[_rank]){
                for (int j = 1;j <= m; j++){
                    if (!vis[j]){
                        b[j] -= abs(i-j);
                    }
                }
            }
        }
        //step 8 統計 s 中的各個字元的個數
        map<char,int> dic;dic.clear();
        for (int i = 0;i < (int)s.size(); i++){
            dic[s[i]]++;
        }
        map<char,int>::iterator it = dic.end();
        it--;

        char ans[N+10];
        //step 9 check 第 i 大的字元是什麼
        for (int i = 1;i <= _rank; i++){
            pair<char,int> temp = *(it);
            while (temp.second < (int)v[i].size()){
                it--;
                temp = *(it);
            }
            // step 10 把相應排序的位置都賦成對應字母
            for (int idx:v[i]){
                ans[idx] = temp.first;
            }
            it--;
        }
        for (int i = 1;i <= m; i++){
            cout << ans[i];
        }
        cout << endl;
    }
    return 0;
}