AcWing 1996. 打乱字母
题目描述
农夫约翰将按字典序排列的 N 头奶牛的名字列表贴在了牛棚的门上。
每个奶牛的名字都由一个长度介于 1 到 20 之间的由小写字母构成的唯一字符串表示。
麻烦制造者贝茜将列表中的奶牛名字重新排序打乱了列表。
此外,她还对每头奶牛的名字中的字母顺序进行了重新排列(也可能保持不变)。
给定修改过后的列表,请帮助约翰确定列表中的每个名字可能出现在原始列表中的最低和最高位置。
输入格式
第一行包含整数 N。
接下来 N 行,按照修改过后列表的顺序,给出了修改过后的奶牛的名字。
输出格式
共 N 行,第 i 行输出给定的第 i 个字符串在原始列表中可能的最低和最高位置。
数据范围
1≤N≤50000
输入样例:
4
essieb
a
xzy
elsie
输出样例:
2 3
1 1
4 4
2 3
样例解释
无论如何,字符串 “a” 必然出现在原始列表中第一个,类似的,字符串 “xzy” 必然出现在原始列表中的最后一个。
而字符串 “essieb” 和 “elsie” 都有可能位于原始列表的第 2 位或第 3 位,这取决于它们的原始字母顺序。
例如,”bessie” 和 “elsie” 分别位于 2,3 位,”sisbee” 和 “ilees” 分别位于 3,2 位。
解题思路
将字符串的正字典序形式与其他字符串的倒字典序形式比较得最高位置
同理,将字符串的倒字典序形式与其他字符串的正字典序形式比较得最低位置
排序想要位置好就得以己之长攻彼之短好叭
然后考虑一下相等的时候就好,一个我要站前边,一个我就要往后站,他是不一样的
爆掉的代码
#include<iostream>
#include<algorithm>
using namespace std;
string minc[50000];
string maxc[50000];
int n;
int min(int index) {
int num = 1;
for (int i = 0; i < n; ++i) {
if (i != index) {
if (minc[index] > maxc[i]) {
num++;
}
}
}
return num;
}
int max(int index) {
int num = 1;
for (int i = 0; i < n; ++i) {
if (i != index) {
if (maxc[index] >= minc[i]) {
num++;
}
}
}
return num;
}
int main() {
cin >> n;
string str;
for (int i = 0; i < n; ++i) {
cin >> str;
sort(str.begin(), str.end());//默认升序
minc[i] = str;
sort(str.rbegin(), str.rend());//降序排序
maxc[i] = str;
}
cout << min(0) << " " << max(0);
for (int i = 1; i < n; ++i) {
cout <<endl<< min(i) << " " << max(i);
}
return 0;
}
修改办法
每次都要从头到尾比较一遍太麻烦了哈
https://www.acwing.com/solution/content/82736/
参考上面题解,先把所有的最大形式排过序,最小形式也是,然后用下面那两个函数(利用二分查找)找位置
lower_bound(begin,end,num)//返回begin到end-1范围内第一个大于或等于num的数字的地址
upper_bound(begin,end,num)//返回begin到end-1范围内第一个大于num的数字的地址
//返回的地址减去起始地址begin,得到找到数字在数组中的下标。
通过代码
#include<iostream>
#include<algorithm>
using namespace std;
string minc[50000];
string maxc[50000];
string m0[50000];
string m1[50000];
int n;
int main() {
cin >> n;
string str;
for (int i = 0; i < n; ++i) {
cin >> str;
sort(str.begin(), str.end());
minc[i] = str;
m0[i] = minc[i];
sort(str.rbegin(), str.rend());
maxc[i] = str;
m1[i] = maxc[i];
}
sort(m0, m0 + n);
sort(m1, m1 + n);
for (int i = 0; i < n; ++i) {
int minIndex, maxIndex;
minIndex = lower_bound(m1, m1 + n, minc[i]) - m1 + 1;
maxIndex = upper_bound(m0, m0 + n, maxc[i]) - m0;
cout << minIndex << " " << maxIndex << endl;
}
return 0;
}
亿点点问题
最好还是用vector存数据哈,我比较懒,直接搞数组好写一点
爆掉的代码里可以看到我没有让一个字符串自己的正、倒字典序形式去进行比较哈,我个人觉得应该是要考虑这个事的
但使用函数之后就不大好写了,我看了几份题解好像也没有管,重点是他通过了,他过了宁晓得伐
emmmm,开心又秃头,有能给孩子解释一下的告诉我哈