总共有 cow 头牛,type 类形容词,有 numi 个第 i 类形容词,第 i 类的第 j 种形容词是 adji,j ,每头牛都需要有这 type 类形容词按照顺序来修饰。现在告诉你要删除这 cow 头牛中的 n 头,问你在这剩下的 cow−n 头牛中,按照字典序排序,排在第 k 位的牛是哪一头?
至此,我们已经能计算出所有牛中排在第 k 个的牛了,但是题目问的是在这剩下的 cow−n 头牛中,按照字典序排序,排在第 k 位的牛是哪一头。
这个小问题的求解就比较简单了,我们可以把 k 转化成在所有牛中的排名,而不是剩下的牛的排名,我们可以先计算出要删除的那 n 头牛在所有牛中的排名,如果这 n 头牛中有牛的排名比 k 小,或是等于 k ,那么就需要把 k 加 1。(相当于排名前 k 的这些牛中有一些是不能选取的,而我们要选出 k 头,所以要加上删去的 n 头牛中排名比 k 小的)
#include<bits/stdc++.h> usingnamespace std; #define ll long long int n, k; int adj_num = 0; vector<string> str[105]; //str[i]表示用于修饰第i头牛的形容词 vector<string> adj_by_pos[35]; //adj_by_pos[i]表示所有在位置i出现的形容词 set<string> is_appear[35]; //is_appear[i]用于判断在位置i上,某个形容词是否出现 int weight_in_pos[35]; //每一位代表的值(按照字典序排在第几) map<string, int> rank_in_pos[35]; //rank_in_pos[i][j]代表在位置i上,字符串j按照字典序排序,排在第几 int cow_rank[105]; //fj没有的牛的排名 bool debug = false; //调试开关,可以打开去体会一下解题的过程 voidmapping()//对每类形容词进行字典序排序,把结果存在 rank[i][j]中,其中 i 代表形容词类型,j 代表排名 { //注意这里的排名从0开始(这是把单词映射到数字上,数字是从0开始的) for (int i = 1; i <= adj_num; i++) { int rank = 0; for (auto j : adj_by_pos[i]) //c++11的新特性,意思是用j遍历所有adj_by_pos[i]的元素 { rank_in_pos[i][j] = rank; if (debug) cout << j << " rank = " << rank << " i = " << i << endl; rank++; } } }
intget_pos(int cow_id) { int ans = 0; for (int i = 1; i <= adj_num; i++) { ans += weight_in_pos[i] * (rank_in_pos[i][str[cow_id][i - 1]]); } return ans + 1; //答案可能是0,但是排位应该从1开始 }
intmain() { ios::sync_with_stdio(false); cin >> n >> k; string temp_str; for (int i = 1; i <= n; i++) { cin >> temp_str; while (temp_str != "no") { cin >> temp_str; } int adj_pos = 1;
while (1) { cin >> temp_str; if (temp_str == "cow.") { break; } str[i].push_back(temp_str); if (!is_appear[adj_pos].count(temp_str)) //还没有出现过,这里是去重操作 { adj_by_pos[adj_pos].push_back(temp_str); is_appear[adj_pos].insert(temp_str); } if (i == 1) { adj_num++; //计算形容词的种类数 } adj_pos++; } } for (int i = 1; i <= adj_num; i++) { sort(adj_by_pos[i].begin(), adj_by_pos[i].end()); //对每个类型的形容词进行排序 }