#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; /* 对线段树离散化的理解, 把单位区间比较多,但是程序中有用不到那么多单位小区间,这时可以用线段树的离散化来处理, 比如[1 3], [2 10], [4 6], [20 10000000] 可以离散化为 [1 3] [2 7] , [5 6], [8 9]; 这样 我们就可以开一个a[10] 的数组来存储就行了, 节省大量的内存 开支, 离散化 ,白话一点 就是区间按不等 但合理的方式,缩小的产物, 以上为基本思想,其能演变的阵法,就靠自己的变通能力了。 */ const int M = 10005; struct node { int l, r; int value; }Tree[16*M]; int n, T; int vist[4*M]; int num[4*M];//辅助离散化, int post[M][2];//存储海报前端和后端, int num2[4*M];//存储离散化后的数, int ans; int Find(int l, int r, int x) { int mid; while(l <= r) { mid = (l + r)/2; if(num2[mid] == x) return mid; else if(num2[mid] > x) { r = mid - 1; } else { l = mid + 1; } } return 0; } void Make_Tree(int x, int y, int nu) { Tree[nu].l = x; Tree[nu].r = y; Tree[nu].value = 0; if(x == y) return; else { int mid = (x + y)/2; Make_Tree(x, mid, nu*2); Make_Tree(mid + 1, y, nu*2 + 1); } } void Add(int x, int y, int c, int nu) { if(Tree[nu].l >= x && Tree[nu].r <= y)//整个区间都被覆盖, { Tree[nu].value = c; return ; } else { int mid; if(Tree[nu].value > 0)//当前区间如果被覆盖过, 则整个区间都被覆盖着,向下传时,也将覆盖整个子区间, { Tree[nu*2].value = Tree[nu].value; Tree[nu*2 + 1].value = Tree[nu].value; Tree[nu].value = 0; } mid = (Tree[nu].l + Tree[nu].r)/2;//向下查找,当前区间能够覆盖的子区间, if(x <= mid) Add(x, y, c, nu*2); if(y > mid) Add(x, y, c, nu*2 +1); } } void query(int x, int y, int nu) { if(Tree[nu].value > 0) { //表示 此区间当前被覆盖; int in = Tree[nu].value; if(!vist[in]) { ans++; vist[in] = 1; } return; } else { //继续查找被覆盖的小区间, if(x == y) return; int mid = (x + y)/2; query(x, mid, nu*2); query(mid +1, y, nu*2 + 1); } } int main() { scanf("%d", &T); while(T--) { memset(Tree, 0, sizeof(Tree)); memset(num, 0, sizeof(num)); memset(post, 0, sizeof(post)); memset(num2, 0, sizeof(num2)); memset(vist, 0, sizeof(vist)); ans = 0; scanf("%d", &n); int k = 0; for(int i = 1; i <= n; i++) { scanf("%d%d", &post[i][0], &post[i][1]); num[++k] = post[i][0]; num[++k] = post[i][1]; } sort(num + 1, num + k + 1); k = unique(num + 1, num + k + 1) - num; k = k - 1; int kn = 0; for(int i = 1; i <= k; i++)//离散化; { if(i > 1 && num[i] > num[i-1] + 1) { num2[++kn] = num[i-1] + 1; } num2[++kn] = num[i]; } Make_Tree(1, kn, 1); int xn, yn; for(int i = 1; i <= n; i++) { xn = Find(1, kn, post[i][0]); yn = Find(1, kn, post[i][1]); Add(xn, yn, i, 1); } query(1, kn, 1); printf("%d\n", ans); } return 0; }
poj 2528 经典线段树入门
最新推荐文章于 2023-06-21 14:19:30 发布