POJ 1436 Horizontally Visible Segments
线段树处理染色问题,把线段排序,从左往右扫描处理出每个线段能看到的右边的线段,然后利用bitset维护枚举两个线段,找出另一个两个都有的线段
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <bitset> #include <vector> using namespace std; const int N = 8005; bitset<N> g[N]; int t, n; struct Seg { int x, y1, y2; void read() { scanf("%d%d%d", &y1, &y2, &x); } } s[N]; bool cmp(Seg a, Seg b) { return a.x < b.x; } #define lson(x) ((x<<1)+1) #define rson(x) ((x<<1)+2) struct Node { int l, r, val, setv; } node[N * 4 * 2]; void pushup(int x) { if (node[lson(x)].val == node[rson(x)].val) node[x].val = node[lson(x)].val; else node[x].val = -1; } void pushdown(int x) { if (node[x].setv != -1) { node[lson(x)].val = node[rson(x)].val = node[x].setv; node[lson(x)].setv = node[rson(x)].setv = node[x].setv; node[x].setv = -1; } } void build(int l, int r, int x = 0) { node[x].l = l; node[x].r = r; node[x].val = -1; node[x].setv = -1; if (l == r) return; int mid = (l + r) / 2; build(l, mid, lson(x)); build(mid + 1, r, rson(x)); } vector<int> g2[N]; void add(int l, int r, int v, int x = 0) { if (node[x].val != -1 && node[x].l >= l && node[x].r <= r) { if (g[node[x].val][v] == false) g2[node[x].val].push_back(v); g[node[x].val][v] = true; node[x].setv = v; node[x].val = v; return; } if (node[x].l == node[x].r) { node[x].val = v; return; } pushdown(x); int mid = (node[x].l + node[x].r) / 2; if (l <= mid) add(l, r, v, lson(x)); if (r > mid) add(l, r, v, rson(x)); pushup(x); } int main() { scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 0; i < n; i++) { g[i].reset(); g2[i].clear(); s[i].read(); } sort(s, s + n, cmp); build(0, N * 2 - 1); for (int i = 0; i < n; i++) add(s[i].y1 * 2, s[i].y2 * 2, i); int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < g2[i].size(); j++) { if (g[i][g2[i][j]]) ans += (g[i]&g[g2[i][j]]).count(); } } printf("%d\n", ans); } return 0; }
时间: 2024-10-14 16:22:35