image.png
image.png
农夫约翰将按字典序排列的 NN 头奶牛的名字列表贴在了牛棚的门上。
每个奶牛的名字都由一个长度介于 11 到 2020 之间的由小写字母构成的唯一字符串表示。
麻烦制造者贝茜将列表中的奶牛名字重新排序打乱了列表。
此外,她还对每头奶牛的名字中的字母顺序进行了重新排列(也可能保持不变)。
给定修改过后的列表,请帮助约翰确定列表中的每个名字可能出现在原始列表中的最低和最高位置。

输入格式

第一行包含整数 NN。
接下来 NN 行,按照修改过后列表的顺序,给出了修改过后的奶牛的名字。

输出格式

共 NN 行,第 ii 行输出给定的第 ii 个字符串在原始列表中可能的最低和最高位置。

数据范围

1≤N≤500001≤N≤50000

输入样例:

4 essieb a xzy elsie

输出样例:

2 3 1 1 4 4 2 3

样例解释

无论如何,字符串 “a” 必然出现在原始列表中第一个,类似的,字符串 “xzy” 必然出现在原始列表中的最后一个。
而字符串 “essieb” 和 “elsie” 都有可能位于原始列表的第 22 位或第 33 位,这取决于它们的原始字母顺序。
例如,”bessie” 和 “elsie” 分别位于 2,32,3 位,”sisbee” 和 “ilees” 分别位于 3,23,2 位。


  1. //定义b,c分别为最大值排序 和最小值排序
  2. //然后运用贪心 让a[i]从小到大排列 然后到b中二分找到最靠前的位置即为最低位置,反之c中最高位置
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <cstring>
  6. using namespace std;
  7. const int N = 50010;
  8. //a[i]原始序列,b[i]从大到小序列,c[i]从小到大序列
  9. string a[N],b[N],c[N];
  10. int n;
  11. int main(){
  12. cin >> n;
  13. for (int i = 1; i <= n; ++i) {
  14. cin >> a[i];
  15. b[i] = c[i] = a[i];
  16. sort(b[i].begin(),b[i].end(),greater<char>());
  17. sort(c[i].begin(),c[i].end());
  18. }
  19. //对b,c排序
  20. sort(b+1,b+n+1);
  21. sort(c+1,c+n+1);
  22. for (int i = 1; i <= n; ++i) {
  23. sort(a[i].begin(),a[i].end());
  24. int l = 1, r = n;
  25. while (l < r) {
  26. int mid = l + r >> 1;
  27. if (b[mid] >= a[i]) r = mid;
  28. else l = mid + 1;
  29. }
  30. cout << l << ' ';
  31. l = 1, r = n;
  32. //让a[i]从大到小
  33. reverse(a[i].begin(),a[i].end());
  34. while (l < r) {
  35. int mid = l + r + 1 >> 1;
  36. if (c[mid] <= a[i]) l = mid;
  37. else r = mid-1;
  38. }
  39. cout << l << endl;
  40. }
  41. return 0;
  42. }