补题记录:E. Correct Placement
补题记录:E. Correct Placement
学到了新的搜索技巧
E. Correct Placement
题意:给你一个矩形纸片,有h, w两个参数,当且仅当\(h_i < h_j \&\& w_i < w_j\)或者\(h_i < w_j \&\& w_i < h_j\),两者满足其一,则称纸片i可以放到j上,对于给定的每张纸片,输出可以放在其上面的序号,如果没有就输出-1
方法:排序
一开始我们很容易想到二分这个方法,我一开始用的是先保证一张纸片的\(h < w\)然后对h进行二分搜索,输出h相同的里面w最小的一个即可。后来wa了一遍找到了反例,还是采用了提交的代码里大多数人用的方法。
我们将所有的h和w进行排序,其中一个升序一个降序。由于找到一个满足的即可,于是我们排序完之后,遍历数组,h已经是从小到大的了,只要看w满不满足目前我们找到的w最小值,因为我们之前找到的w中,h一定是比当前的要小的,所以如果满足w > minw的话说明一定满足,记录答案即可,具体看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
inline int lc(int u) {return u << 1;}
inline int rc(int u) {return u << 1 | 1;}
inline int lowbit(int x) {return x & (-x);}
struct node {
int h, w, idx;
bool operator < (const node &B) const {
if (h != B.h) return h < B.h;
return w < B.w;
}
} a[N];
inline void solve() {
int n; cin >> n;
vector<node> p(n * 2);
for (int i = 0; i < n; i ++ ) {
int h, w; cin >> h >> w;
p[i] = {h, -w, i + 1};
p[i + n] = {w, -h, i + 1};
}
sort(p.begin(), p.end());
vector<int> res(n + 1, -1);
int mnw = 2e9, id = -1;
for (auto &ite : p) {
int h = ite.h, w = -ite.w, idx = ite.idx;
if (w > mnw) res[idx] = id;
else if (w < mnw){
mnw = w;
id = idx;
}
}
for (int i = 1; i <= n; i ++ ) cout << res[i] << ' ';
cout << endl;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int t; cin >> t;
while (t -- )
solve();
return 0;
}