Azulejos
Azulejo in the cathedral of Porto. Source: Wikimedia Commons
Ceramic artists Maria and João are opening a small azulejo store in Porto. Azulejos are the beautiful ceramic tiles for which Portugal is famous. Maria and João want to create an attractive window display, but, due to limited space in their shop, they must arrange their tile samples in two rows on a single shelf. Each of João’s tiles has exactly one of Maria’s tiles in front of it and each of Maria’s tiles has exactly one of João’s tiles behind it. These hand-crafted tiles are of many different sizes, and it is important that each tile in the back row is taller than the tile in front of it so that both are visible to passers-by. For the convenience of shoppers, tiles in each row are arranged in non-decreasing order of price from left to right. Tiles of the same price may be arranged in any order subject to the visibility condition stated above.
Your task is to find an ordering of the tiles in each row that satisfies these constraints, or determine that no such ordering exists.
Input
The first line of input contains an integer nn (1≤n≤5⋅1051≤n≤5⋅105), the number of tiles in each row. The next four lines contain nn integers each; the first pair of lines represents the back row of tiles and the second pair of lines represents the front row. Tiles in each row are numbered from 11 to nn according to their ordering in the input. The first line in each pair contains nn integers p1,…,pnp1,…,pn (1≤pi≤1091≤pi≤109 for each ii), where pipi is the price of tile number iiin that row. The second line in each pair contains nn integers h1,…,hnh1,…,hn (1≤hi≤1091≤hi≤109 for each ii), where hihi is the height of tile number ii in that row.
Output
If there is a valid ordering, output it as two lines of nn integers, each consisting of a permutation of the tile numbers from 11 to nn. The first line represents the ordering of the tiles in the back row and the second represents the ordering of the tiles in the front row. If more than one pair of permutations satisfies the constraints, any such pair will be accepted. If no ordering exists, output impossible.
Sample Input 1 | Sample Output 1 |
---|---|
|
|
Sample Input 2 | Sample Output 2 |
---|---|
|
|
题目链接:https://judge.icpc.global/problems/azulejos
题目大意:一共有两层,每层放n个物品,每个物品有高度和价格两个属性,放的时候要求两层物品的价格从左往右不降序,且前一层物品的高度严格小于后一层对应位置物品的高度,给出一种可行的摆放策略
题目分析:首先两层均按价格从小到大排序,价格相同的位置可以任意交换,因此对于两层分别维护价格相同的区间,优先匹配区间元素少的一层,方法是去另一层的区间中找高度和其最接近且满足条件的位置,若某次找不到,则说明无解,用set维护,找的时候直接二分,时间复杂度O(nlogn)
附一组数据
Sample Input 2 | Sample Output 2 |
---|---|
|
|
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
int const MAX = 5e5 + 5;
int n, h, p;
struct Tile {
int id, h, p;
}b[MAX], f[MAX];
bool cmp(Tile a, Tile b) {
return a.p < b.p;
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &b[i].p);
}
for (int i = 0; i < n; i++) {
b[i].id = i + 1;
scanf("%d", &b[i].h);
}
for (int i = 0; i < n; i++) {
scanf("%d", &f[i].p);
}
for (int i = 0; i < n; i++) {
f[i].id = i + 1;
scanf("%d", &f[i].h);
}
sort(b, b + n, cmp);
sort(f, f + n, cmp);
// for (int i = 0; i < n; i++) {
// printf("%d(%d,%d) ", b[i].h, b[i].id, b[i].p);
// }
// printf("\n");
// for (int i = 0; i < n; i++) {
// printf("%d(%d,%d) ", f[i].h, f[i].id, f[i].p);
// }
// printf("\n");
vector<int> b_ans(n);
vector<int> f_ans(n);
set< pair<int, int> > b_s;
set< pair<int, int> > f_s;
set< pair<int, int> > :: iterator b_it;
set< pair<int, int> > :: iterator f_it;
int b_idx = 0, f_idx = 0;
for (int i = 0; i < n; i++) {
if (b_s.empty()) {
while (b_idx < n) {
b_s.insert(make_pair(b[b_idx].h, b[b_idx].id));
b_idx++;
if (b[b_idx].p != b[b_idx - 1].p) {
break;
}
}
}
if (f_s.empty()) {
while (f_idx < n) {
f_s.insert(make_pair(f[f_idx].h, f[f_idx].id));
f_idx++;
if (f[f_idx].p != f[f_idx - 1].p) {
break;
}
}
}
// printf("b_s size = %lu f_sz size = %lu\n", b_s.size(), f_s.size());
if (b_s.size() < f_s.size()) {
int curbh = b_s.begin() -> first;
int curbid = b_s.begin() -> second;
f_it = f_s.lower_bound(make_pair(curbh, -1));
if (f_it == f_s.begin()) {
printf("impossible\n");
return 0;
}
f_it = prev(f_it);
b_ans[i] = curbid;
b_s.erase(b_s.begin());
f_ans[i] = f_it -> second;
f_s.erase(f_it);
} else {
int curfh = f_s.begin() -> first;
int curfid = f_s.begin() -> second;
b_it = b_s.upper_bound(make_pair(curfh, n + 1));
if (b_it == b_s.end()) {
printf("impossible\n");
return 0;
}
f_ans[i] = curfid;
f_s.erase(f_s.begin());
b_ans[i] = b_it -> second;
b_s.erase(b_it);
}
}
int sz = b_ans.size();
for (int i = 0; i < sz; i++) {
printf("%d%c", b_ans[i], i == (sz - 1) ? '\n' : ' ');
}
for (int i = 0; i < sz; i++) {
printf("%d%c", f_ans[i], i == (sz - 1) ? '\n' : ' ');
}
}