(题面来自AcWing)
有N个元素,编号1.2..N,每一对元素之间的大小关系是确定的,关系不具有传递性。
也就是说,元素的大小关系是N个点与N*(N-1)/2条有向边构成的任意有向图。
然而,这是一道交互式试题,这些关系不能一次性得知,你必须通过不超过10000次提问来获取信息,每次提问只能了解某两个元素之间的关系。
现在请你把这N个元素排成一行,使得每个元素都小于右边与它相邻的元素。
你可以通过我们预设的bool函数compare来获得两个元素之间的大小关系。
例如,编号为a和b的两个元素,如果元素a小于元素b,则compare(a,b)返回true,否则返回false。
将N个元素排好序后,把他们的编号以数组的形式输出,如果答案不唯一,则输出任意一个均可。
数据范围
1≤N≤1000
遇到的第一道交互题。看到N的范围考虑插入排序:我们每次在原序列中找出合适的位置,把新的数字插入。题中要求询问小于等于10000次,大约是NogN的范围,那么就来二分了。
二分时每次check一下数组中当前元素ans[mid]与i的关系;如果i < ans[mid],则说明mid的左边一定存在一个位置k满足ans[k] > i && ans[k - 1] < i,否则左边的数都大于i,插入到第一个位置即可。同理,i > ans[mid]就往右边插入。因为是向下取整二分,最终得到的ans[l]是大于i的第一个数。注意特判ans[l]也小于i的边界。
代码:
- // Forward declaration of compare API.
- // bool compare(int a, int b);
- // return bool means whether a is less than b.
- class Solution {
- public:
- vector<int> specialSort(int N) {
- vector<int> ans;
- ans.push_back(1);
- for (int i = 2; i <= N; ++i) {
- int l = 0, r = ans.size() - 1;
- while (l < r) {
- int mid = l + r >> 1;
- if (compare(i, ans[mid]))
- r = mid;
- else l = mid + 1;
- }
- ans.push_back(i);
- if (compare(ans[l], i)) continue;
- for (int j = ans.size() - 2; j >= l; --j)
- swap(ans[j], ans[j + 1]);
- }
- return ans;
- }
- };
原文地址:https://www.cnblogs.com/TY02/p/11332505.html
时间: 2024-10-09 01:31:18