本题就是要往墙上贴海报,问最后有多少可见的海报。
事实上本题的难点并非线段树,而是离散化。
由于数据非常大,直接按原始数据计算那么就会爆内存和时间的。
故此须要把数据离散化。
比方有海报1 6 7 9 20 100 5 1000的原始数据。直接计算须要1-1000的内存,离散化之后仅仅须要8内存,由于仅仅有4组数据8个数。
本题更进一步高级一点的离散化就是须要把不相邻的两个数据插入一个数值。表示有空白的地方,不是全部海报都覆盖到的。
比方上面的数据要离散为:1 2 5 6 7 8 9 10 20 21 100 101 1000,中间插入了一些数值,这样才干保证数据正确。
比較难想出来的地方。须要好好考虑一下才干想通的。
看程序discreteArr是离散化之后的数据。使用这种数据处理就能够比原始数据少非常多数据了。
#include <stdio.h> #include <cstring> #include <algorithm> using namespace std; const int SIZE = 10005; bool hashColor[SIZE]; int le[SIZE], ri[SIZE]; int discreteArr[SIZE<<2];//由于这里或许须要四倍的SIZE内存 int seg[SIZE<<4]; int visiblePosts; inline int lChild(int rt) { return rt<<1; } inline int rChild(int rt) { return rt<<1|1; } inline void pushDown(int rt) { if (seg[rt]) { seg[lChild(rt)] = seg[rChild(rt)] = seg[rt]; seg[rt] = 0; } } void build(int l, int r, int rt) { seg[rt] = 0; if (l == r) return ; int m = l + ((r-l)>>1); build(l, m, lChild(rt)); build(m+1, r, rChild(rt)); } void update(int ql, int qr, int col, int l, int r, int rt) { if (ql <= l && r <= qr) { seg[rt] = col; return; } pushDown(rt); int m = l + ((r-l)>>1); if (ql <= m) update(ql, qr, col, l, m, lChild(rt)); if (m < qr) update(ql, qr, col, m+1, r, rChild(rt)); } void query(int l, int r, int rt) { if (seg[rt]) { if (!hashColor[seg[rt]]) { visiblePosts++; hashColor[seg[rt]] = true; } return ; } if (l == r) return ;//注意这里没有poster的时候 int m = l + ((r-l)>>1); query(l, m, lChild(rt)); query(m+1, r, rChild(rt)); } int biSearch(int arr[], int key, int n) { int l = 1, r = n-1, m = -1; while (l <= r) { m = l + ((r-l)>>1); if (arr[m] < key) l = m+1; else if (key < arr[m]) r = m-1; else break; } return m; } int main() { int T, n; scanf("%d", &T); while (T--) { scanf("%d", &n); int disN = 1; for (int i = 1; i <= n; i++) { scanf("%d %d", &le[i], &ri[i]); discreteArr[disN++] = le[i]; discreteArr[disN++] = ri[i]; } sort(discreteArr+1, discreteArr+disN); int j = 2; for (int i = 2; i < disN; i++) { if (discreteArr[i] != discreteArr[i-1]) discreteArr[j++] = discreteArr[i]; } for (int i = j-1; i > 1; i--) { if (discreteArr[i] != discreteArr[i-1] + 1) discreteArr[j++] = discreteArr[i-1] + 1; } sort(discreteArr + 1, discreteArr + j); build(1, j-1, 1); for (int i = 1; i <= n; i++) { int ql = biSearch(discreteArr, le[i], j); int qr = biSearch(discreteArr, ri[i], j); update(ql, qr, i, 1, j-1, 1); } visiblePosts = 0; memset(hashColor, 0, sizeof(bool) * (n+1)); query(1, j-1, 1); printf("%d\n", visiblePosts); } return 0; }
POJ 2528 Mayor's posters 离散化和线段树题解
时间: 2024-10-15 22:03:40