AcWing 113. 特殊排序()-其他
AcWing 113. 特殊排序()
有关数据
\(\texttt{Time Limit}\) | \(\texttt{Memory Limit}\) | \(\texttt{Difficulty}\) |
---|---|---|
\(\color{green}{\texttt{1 sec}}\) | \(\color{red}{\texttt{64 MB}}\) | \(\color{blue}{\texttt{Easy}}\) |
题目大意
有 \(N\) 个元素,编号 \(1,2\cdots,N\),每一对元素之间的大小关系是确定的,关系具有反对称性,但不具有传递性。
注意:不存在两个元素大小相等的情况。
也就是说,元素的大小关系是 \(N\) 个点与 \(\frac{N\times(N1)}{2}\) 条有向边构成的任意有向图。
然而,这是一道交互式试题,这些关系不能一次性得知,你必须通过不超过 \(10000\) 次提问来获取信息,每次提问只能了解某两个元素之间的关系。
将 ¥N¥ 个元素排好序后,把他们的编号以数组的形式输出,如果答案不唯一,则输出任意一个均可。
提示
- \(1 \leq N \leq 1000\)
解法分析
这道题我们采用二分。
首先,考虑归纳法。如果已经确定了前 \(k-1\) 个元素的大小关系,那么对于第 \(k\) 个数,我们可以尝试二分。
因为前 \(k-1\) 个数是单调递增的,所以二分前 \(k-1\) 个数。如果小于,往上区间走;否则,往下区间走。这样,总的询问次数是 \(n\log{n}\),题目可以接受。
至此,我们做出了这一题。
至于为什么二分一定能搜到……?这需要说吗?
AC Code
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define lf double
# define GO(i,a,b) for(ll i = a; i <= b; i ++)
# define RO(i,b,a) for(ll i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define MP(a,b) make_pair(a, b)
# define PB push_back
# define mem(a,x) memset(a, x, sizeof a)
# define F first
# define S second
// 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.PB(1);
GO (i, 2, n){
int l = 1, r = i - 1;
int pos = 0;
while (l <= r){
int mid = (l + r) >> 1;
bool res = compare(ans[mid - 1], i);
if (res){
pos = mid;
l = mid + 1;
}
else r = mid - 1;
}
ans.insert(ans.begin() + pos, i);
}
return ans;
}
};
有关数据
\(\texttt{Time Limit}\) | \(\texttt{Memory Limit}\) | \(\texttt{Difficulty}\) |
---|---|---|
\(\color{green}{\texttt{1 sec}}\) | \(\color{red}{\texttt{64 MB}}\) | \(\color{blue}{\texttt{Easy}}\) |
题目大意
有 \(N\) 个元素,编号 \(1,2\cdots,N\),每一对元素之间的大小关系是确定的,关系具有反对称性,但不具有传递性。
注意:不存在两个元素大小相等的情况。
也就是说,元素的大小关系是 \(N\) 个点与 \(\frac{N\times(N1)}{2}\) 条有向边构成的任意有向图。
然而,这是一道交互式试题,这些关系不能一次性得知,你必须通过不超过 \(10000\) 次提问来获取信息,每次提问只能了解某两个元素之间的关系。
将 ¥N¥ 个元素排好序后,把他们的编号以数组的形式输出,如果答案不唯一,则输出任意一个均可。
提示
- \(1 \leq N \leq 1000\)
解法分析
这道题我们采用二分。
首先,考虑归纳法。如果已经确定了前 \(k-1\) 个元素的大小关系,那么对于第 \(k\) 个数,我们可以尝试二分。
因为前 \(k-1\) 个数是单调递增的,所以二分前 \(k-1\) 个数。如果小于,往上区间走;否则,往下区间走。这样,总的询问次数是 \(n\log{n}\),题目可以接受。
至此,我们做出了这一题。
至于为什么二分一定能搜到……?这需要说吗?
AC Code
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define lf double
# define GO(i,a,b) for(ll i = a; i <= b; i ++)
# define RO(i,b,a) for(ll i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define MP(a,b) make_pair(a, b)
# define PB push_back
# define mem(a,x) memset(a, x, sizeof a)
# define F first
# define S second
// 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.PB(1);
GO (i, 2, n){
int l = 1, r = i - 1;
int pos = 0;
while (l <= r){
int mid = (l + r) >> 1;
bool res = compare(ans[mid - 1], i);
if (res){
pos = mid;
l = mid + 1;
}
else r = mid - 1;
}
ans.insert(ans.begin() + pos, i);
}
return ans;
}
};