P3087 [USACO13NOV]Farmer John has no Large Brown Cow S(进制)

就是进制转换。

先预处理每种形容词的个数,排序。

然后求出个牛当前的排名。

然后对这头牛排序。

更新实际的

然后再倒着从左往右求出每个进制位上的数字即可。

#include <bits/stdc++.h>
using namespace 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; //调试开关,可以打开去体会一下解题的过程
void mapping() //对每类形容词进行字典序排序,把结果存在 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++;
}
}
}

int get_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开始
}

int main()
{
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()); //对每个类型的形容词进行排序
}

weight_in_pos[adj_num + 1] = 1; //第一位代表的数字应该是1
adj_by_pos[adj_num + 1].push_back("temp"); //1和1相乘是1,所以要push一个元素进去,这样子size就是1

for (int i = adj_num; i >= 1; i--) //计算每一位在十进制中代表的值(这里的位的计算方法和平时的方法是反的)
{ //这是因为本题中的形容词类型和数字系统的 “位” 是相反的
// if (debug)
// cout << "i" << i << endl;
weight_in_pos[i] = weight_in_pos[i + 1] * adj_by_pos[i + 1].size();
}
mapping();
for (int i = 1; i <= n; i++)
{
cow_rank[i] = get_pos(i); //计算出要删除的n头牛的整体排名
// if (debug)
// cout << "cowrkw " << i << " = " << cow_rank[i] << endl;
}
sort(cow_rank + 1, cow_rank + n + 1); //按照每种牛的排名进行排序
for (int i = 1; i <= n; i++)
{
if (cow_rank[i] <= k)
{
k++;
}
else
{
break;
}
}
k--; //k原本代表的是排在第几的牛,但是我们已经把牛的排名转化成数字了,
//排名最小的牛的数字是0而不是1,所以这里要减1
// if (debug)
// cout << "new k" << k << endl;
for (int i = 1; i <= adj_num; i++)
{
cout << adj_by_pos[i][(k) / weight_in_pos[i]] << " ";
// if (debug)
// cout << "i " << i << " (k) / weight_in_pos[i] " << (k) / weight_in_pos[i] << endl;
k %= weight_in_pos[i];
}
return 0;
}