題目鏈接
線段樹處理染色問題,把線段排序,從左往右掃描處理出每個線段能看到的右邊的線段,然後利用bitset維護枚舉兩個線段,找出另一個兩個都有的線段
代碼:
#include#include #include #include #include using namespace std; const int N = 8005; bitset 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 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; }