【Codeforces Round #650 (Div. 3) D】Task On The Board
阿新 • • 發佈:2020-12-15
題目連結
翻譯
將 \(s\) 刪掉 \(|s|-m\) 個字元之後,剩下的 \(m\) 個字元任意排序得到 \(t\)。根據 \(t\) 上每個字元的字典序的大小關係生成了一個序列 \(b\)。
現在告訴你 \(s\) 以及 \(m\) 和 \(b\) 讓你輸出某個可能的 \(t\)。
題解
\(trick\) 就是每次找到 \(b\) 的值為 \(0\) 的位置,其他不為 \(0\) 的位置,肯定要減去和它的下標的差的絕對值(為 \(0\) 說明對應位置上的字母的字典序最大)
重複上述過程。每次有幾個 \(0\) 就說明有對應數目的字典序的字母。
那麼從'z'到'a'檢視每個字母在 \(s\)
大於等於第 \(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; }