题目链接:【CodeForces 269D】Maximum Waterfall
题目大意:高度为 的墙上有 块木板,每个模板有一个高度 ,左端点 ,右端点 。墙的顶端可以视作一个高度为 ,左端点 ,右端点 的木板,底端同理,可以视作一个高度为 ,左端点 ,右端点 的木板。现在要制造一个瀑布。木板 的水能够流向木板 当且仅当以下 个条件同时满足:
- 不存在木板 ,使得 和 同时满足前两个条件。
如果三个条件同时满足,则木板 到木板 的最大流量为: 。瀑布是一条路径,从墙的顶端到墙的底端。瀑布的流量是瀑布中相邻两个木板流量的最小值。求最大瀑布流量。请结合样例理解。
Sample Input:
5 6
4 1 6
3 2 7
5 9 11
3 10 15
1 13 16
Sample Output:
4
首先,发现 的对数是 的,并且只需要知道所有的 ,就很容易 。所以问题的关键就是找到所有的 找出来。
将每个端点放进一个 中,排序后从左到右扫。如果是右端点,则删除这块木板;否则,往数据结构中添加这块木板,并找到第一块比他高的木板和第一块比他低的木板。如果第一块比他高的木板可以到达第一块比他低的木板,则他们之间的边就要被这块木板切断。如果这块木板能到达 两块木板,则在他和 两块木板连一条边。
显然可以使用 维护。时间复杂度 。
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
const int maxn = 100005;
int n, m, l[maxn], r[maxn], dp[maxn];
struct point {
int hei, x, type, id;
point() {}
point(int a, int b, int c, int d) {
hei = a, x = b, type = c, id = d;
}
bool operator<(const point &o) const{
return x == o.x ? type == o.type ? id < o.id : type < o.type : x < o.x;
}
};
vector<point> p;
vector<pii> g[maxn];
set<pii> s;
int value(int l0, int r0, int l1, int r1) {
return min(r0, r1) - max(l0, l1);
}
int dfs(int u) {
if (u == n + 1) {
return 2e9;
}
if (~dp[u]) {
return dp[u];
}
for (int a, b, i = 0; i < g[u].size(); i++) {
a = g[u][i].first, b = g[u][i].second;
dp[u] = max(dp[u], min(b, dfs(a)));
}
return dp[u];
}
int main() {
scanf("%d %d", &n, &m);
l[0] = -1e9, r[0] = 1e9;
l[n + 1] = -1e9, r[n + 1] = 1e9;
for (int h, i = 1; i <= n; i++) {
scanf("%d %d %d", &h, l + i, r + i);
p.push_back(point(h, l[i], 1, i));
p.push_back(point(h, r[i], 0, i));
}
sort(p.begin(), p.end());
s.insert(pii(m, 0)), s.insert(pii(0, n + 1));
for (int i = 0; i < p.size(); i++) {
if (p[i].type) {
set<pii>::iterator it = s.insert(pii(p[i].hei, p[i].id)).first;
int down = (--it) -> second, up = (++++it) -> second;
if (g[up].size() && g[up].back().first == down) {
g[up].pop_back();
// printf("%d -x> %d\n", up, down);
}
if (value(l[up], r[up], l[p[i].id], r[p[i].id])) {
g[up].push_back(pii(p[i].id, value(l[up], r[up], l[p[i].id], r[p[i].id])));
// printf("%d --> %d\n", up, p[i].id);
}
if (value(l[p[i].id], r[p[i].id], l[down], r[down])) {
g[p[i].id].push_back(pii(down, value(l[p[i].id], r[p[i].id], l[down], r[down])));
// printf("%d --> %d\n", p[i].id, down);
}
} else {
s.erase(s.find(pii(p[i].hei, p[i].id)));
}
}
memset(dp, -1, sizeof(dp));
printf("%d\n", dfs(0));
return 0;
}