/*
离散化思路 和一般的离散化不同 多了个中间加点操作
具体为啥要加点
1-10 1-4 6-10
这三个区间离散化后 5 这个点会丢掉。
加点防止丢点。。。。。。。hhhh
总结 排序 去重 中间加点 再排序
*/
2528 -- Mayor‘s posters (poj.org)
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1e6 + 10; #define ls (u<<1) #define rs (u<<1|1) struct node { int l, r; }e[maxn]; struct sgt { int l, r; int co; }tr[maxn*20]; int a[maxn], la; int find(int x) { return lower_bound(a + 1, a + 1 + la, x) - a; } int t, n, m; bool vis[maxn]; void build(int u, int l, int r) { tr[u].l=l;tr[u].r=r;tr[u].co=0; if (l == r)return; int mid = (l + r) / 2; build(ls, l, mid); build(rs, mid + 1, r); } void pushdown(int u) { if (tr[u].co > 0) { tr[ls].co = tr[rs].co = tr[u].co; tr[u].co = 0; } } void modify(int u, int ql, int qr,int v) { if (ql <= tr[u].l && tr[u].r <= qr) { tr[u].co = v; return; } pushdown(u); int mid = (tr[u].l + tr[u].r) / 2; if (ql <= mid)modify(ls, ql, qr, v); if (mid < qr)modify(rs, ql, qr, v); } void ask(int u, int& ans) { if (tr[u].co != 0 && vis[tr[u].co] == false)ans++, vis[tr[u].co] = true; if (tr[u].l == tr[u].r)return; pushdown(u); int mid = (tr[u].l + tr[u].r) / 2; ask(ls, ans); ask(rs, ans); } void solve() { la = 0; scanf("%d", &n); for (int i = 1; i <= n; i++)scanf("%d%d", &e[i].l, &e[i].r), a[++la] = e[i].l, a[++la] = e[i].r; sort(a + 1, a + 1 + la);//排序 la = unique(a + 1, a + 1 + la) - a - 1;//去重 for (int i = la; i > 1; i--)if (a[i] - a[i - 1] > 1)a[++la] = a[i-1] +1;//中间加点 sort(a + 1, a + 1 + la);//排序 build(1, 1, la); memset(vis, 0, sizeof vis); for (int i = 1; i <= n; i++) { int l = find(e[i].l), r = find(e[i].r); modify(1, l, r, i); } int ans = 0; ask(1, ans); printf("%d\n", ans); } int main() { scanf("%d", &t); while (t--)solve(); return 0; }