269D
扫描线+dp
先对坐标排序,然后·用set维护端点,每次插入左端点,扫描到右端点时删除。每次考虑新插入时分割了哪两个木板,自己分别连边,再删除原来的边,最后dp(好像得维护used,有环)
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 800010, inf = 2000000010; struct data { int l, r, h; data(int l = 0, int r = 0, int h = 0) : l(l), r(r), h(h) {} } ed[N]; int n, t, cnt; int dp[N], used[N]; PII e[N]; set<PII> s, m; vector<PII> G[N]; void dfs(int u) { if(dp[u] == inf || used[u]) return; used[u] = 1; for(int i = 0; i < G[u].size(); ++i) { PII x = G[u][i]; int v = x.first, w = x.second; dfs(v); dp[u] = max(dp[u], min(dp[v], w)); } } int main() { scanf("%d%d", &n, &t); for(int i = 1; i <= n; ++i) { int h, l, r; scanf("%d%d%d", &h, &l, &r); ed[i] = data(l, r, h); e[++cnt] = make_pair(l, i); e[++cnt] = make_pair(r, -i); } sort(e + 1, e + cnt + 1); ed[n + 1] = data(-inf, inf, 0); ed[n + 2] = data(-inf, inf, t); s.insert(make_pair(0, n + 1)); s.insert(make_pair(t, n + 2)); for(int i = 1; i <= cnt; ++i) { int x = e[i].second; if(x < 0) { s.erase(make_pair(ed[-x].h, -x)); continue; } PII t = make_pair(ed[x].h, x); set<PII> :: iterator it = s.lower_bound(t); PII up = *it; --it; PII low = *it; m.erase(make_pair(up.second, low.second)); m.insert(make_pair(up.second, x)); m.insert(make_pair(x, low.second)); s.insert(t); } for(set<PII> :: iterator it = m.begin(); it != m.end(); ++it) { PII x = *it; int len = min(ed[x.second].r, ed[x.first].r) - max(ed[x.second].l, ed[x.first].l); G[x.second].push_back(make_pair(x.first, len)); } dp[n + 2] = inf; dfs(n + 1); printf("%d\n", dp[n + 1]); return 0; }
线段树维护+dp
这个方法好恶心,调了好长时间,边界搞错。
先离散化坐标,然后按高度排序,正反两次建边。但是一定要注意,边界很恶心,有可能出现1-2,2-3这样的,这样是不相交的。所以右端点要-1就避免了这种情况,因为如果原先只有1单位重合,那么现在不相交了。如果有1单位以上重合,那么现在还是相交的。
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int M = 300010, inf = 2000000010; int n, T, N; vector<PII> G[M]; vector<int> v; map<int, int> mp, mir; int dp[M], used[M]; struct data { int l, r, h; } a[M]; struct seg { int tree[M << 2], tag[M << 2]; void pushdown(int x) { if(!tag[x]) return; tag[x << 1] = tag[x]; tag[x << 1 | 1] = tag[x]; tree[x << 1] = tag[x]; tree[x << 1 | 1] = tag[x]; tag[x] = 0; } void update(int l, int r, int x, int a, int b, int c) { if(l > b || r < a) return; if(l >= a && r <= b) { tree[x] = tag[x] = c; return; } pushdown(x); int mid = (l + r) >> 1; update(l, mid, x << 1, a, b, c); update(mid + 1, r, x << 1 | 1, a, b, c); tree[x] = max(tree[x << 1], tree[x << 1 | 1]); } int query(int l, int r, int x, int a, int b) { if(l > b || r < a) return 0; if(l >= a && r <= b) return tree[x]; pushdown(x); int mid = (l + r) >> 1; return max(query(l, mid, x << 1, a, b), query(mid + 1, r, x << 1 | 1, a, b)); } } t; void construct(int N, bool flag) { memset(t.tree, 0, sizeof(t.tree)); memset(t.tag, 0, sizeof(t.tag)); for(int i = 1; i < n; ++i) { int k = t.query(1, N, 1, a[i].l, a[i].l); int low = max(a[i].l, a[k].l), high = min(a[i].r, a[k].r), len = mir[high] - mir[low]; int tt = t.query(1, N, 1, low, high - 1); if(tt == k && tt) { if(!flag) G[k].push_back(make_pair(i, len)); else G[n - i + 1].push_back(make_pair(n - k + 1, len)); } k = t.query(1, N, 1, a[i].r - 1, a[i].r - 1); low = max(a[i].l, a[k].l), high = min(a[i].r, a[k].r), len = mir[high] - mir[low]; tt = t.query(1, N, 1, low, high - 1); if(tt == k && tt) { if(!flag) G[k].push_back(make_pair(i, len)); else G[n - i + 1].push_back(make_pair(n - k + 1, len)); } t.update(1, N, 1, a[i].l, a[i].r - 1, i); } } void dfs(int u) { if(used[u] || dp[u] == inf) return; used[u] = 1; for(int i = 0; i < G[u].size(); ++i) { PII x = G[u][i]; int v = x.first, w = x.second; dfs(v); dp[u] = max(dp[u], min(dp[v], w)); } } bool cp(data x, data y) { return x.h == y.h ? x.l < y.l : x.h < y.h; } int main() { scanf("%d%d", &n, &T); a[1].h = 0; a[n + 2].h = T; a[1].l = a[n + 2].l = -inf; a[1].r = a[n + 2].r = inf; v.push_back(inf); v.push_back(-inf); for(int i = 1; i <= n; ++i) { scanf("%d%d%d", &a[i + 1].h, &a[i + 1].l, &a[i + 1].r); v.push_back(a[i + 1].l); v.push_back(a[i + 1].r); } sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); N = v.size(); for(int i = 0; i < v.size(); ++i) { mp[v[i]] = i + 1; mir[i + 1] = v[i]; } n += 2; for(int i = 1; i <= n; ++i) { a[i].l = mp[a[i].l]; a[i].r = mp[a[i].r]; } sort(a + 1, a + n + 1, cp); construct(N, false); reverse(a + 1, a + n + 1); construct(N, true); dp[n] = inf; dfs(1); printf("%d\n", dp[1]); return 0; }