题意:要建n个高楼,给出了每个高楼的左右区间和高度,问最后所有的高楼的轮廓包括了哪些点。
题解:这题好坑,用了n种姿势了还是一直wa,后来才直到必须加输入输出文件那句话才能过。。。用线段树存维护区间内最大值也就是高度,左右区间到1e9所以要离散化。因为维护的是每一段的最大值而不是点,所以划分左右子区间那里要把mid到mid+1也归到右子区间里。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 100005;
int n, a[N << 1], h[N], l[N], r[N], hh;
int tree[N << 4], res[N << 3][2];
map<int, int> mp;
void pushdown(int k) {
if (tree[k]) {
tree[k * 2] = max(tree[k * 2], tree[k]);
tree[k * 2 + 1] = max(tree[k * 2 + 1], tree[k]);
tree[k] = 0;
}
}
void modify(int k, int left, int right, int l1, int r1, int x) {
if (l1 <= left && right <= r1) {
tree[k] = max(tree[k], x);
return;
}
pushdown(k);
int mid = (left + right) / 2;
if (l1 < mid)
modify(k * 2, left, mid, l1, r1, x);
if (r1 > mid)
modify(k * 2 + 1, mid, right, l1, r1, x);
}
void query(int k, int left, int right, int l1, int r1) {
if (left + 1 == right) {
hh = tree[k];
return;
}
pushdown(k);
int mid = (left + right) / 2;
if (l1 < mid)
query(k * 2, left, mid, l1, r1);
else
query(k * 2 + 1, mid, right, l1, r1);
}
int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%d", &n);
memset(tree, 0, sizeof(tree));
mp.clear();
int cnt = 0;
for (int i = 1; i <= n; i++) {
scanf("%d%d%d", &h[i], &l[i], &r[i]);
a[cnt++] = l[i];
a[cnt++] = r[i];
}
sort(a, a + cnt);
cnt = unique(a, a + cnt) - a;
for (int i = 0; i < cnt; i++)
mp[a[i]] = i;
for (int i = 1; i <= n; i++)
modify(1, 0, cnt - 1, mp[l[i]], mp[r[i]], h[i]);
int num = 0, curh = 0;
for (int i = 0; i < cnt - 1; i++) {
query(1, 0, cnt - 1, i, i + 1);
if (hh != curh) {
res[num][0] = a[i];
res[num++][1] = curh;
res[num][0] = a[i];
res[num++][1] = hh;
curh = hh;
}
}
if (curh) {
res[num][0] = a[cnt - 1];
res[num++][1] = curh;
res[num][0] = a[cnt - 1];
res[num++][1] = 0;
}
printf("%d\n", num);
for (int i = 0; i < num; i++)
printf("%d %d\n", res[i][0], res[i][1]);
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-12 20:44:45