题目连接:
http://poj.org/problem?id=2528
题目大意:
有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的?
解题思路:
因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL.........
所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,所以我们对每个海报所覆盖的区间也对应建立了一个节点,这样的话线段树有39999个节点。
分析完咯,然后就是建树,还有就是贴海报的时候要倒着贴,这样的话插入海报的时候直接可以判断出来此海报是不是可见。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 10005; 7 struct poster 8 { 9 int l, r; 10 }; 11 struct node 12 { 13 int l, r; 14 bool sta; 15 int Mid() 16 { 17 return ( l + r ) / 2; 18 } 19 }; 20 node tree[16*maxn]; 21 poster pos[maxn]; 22 int hash[maxn*1000], x[maxn*2]; 23 24 void Build (int root, int l, int r) 25 { 26 tree[root].l = l; 27 tree[root].r = r; 28 tree[root].sta = true; 29 if (l == r) 30 return ; 31 Build (2*root+1, l, tree[root].Mid()); 32 Build (2*root+2, tree[root].Mid()+1, r); 33 } 34 35 int update (int root, int l, int r) 36 { 37 if (!tree[root].sta) 38 return 0; 39 if (tree[root].l == l && tree[root].r == r) 40 { 41 tree[root].sta = false; 42 return 1; 43 } 44 int x; 45 if (r <= tree[root].Mid()) 46 x = update (2*root+1, l, r); 47 else if (tree[root].Mid() < l) 48 x = update (2*root+2, l, r); 49 else 50 { 51 int b1 = update (2*root+1, l, tree[root].Mid()); 52 int b2 = update (2*root+2, tree[root].Mid()+1, r); 53 x = b1 || b2; 54 } 55 if (!tree[2*root+1].sta && !tree[2*root+2].sta) 56 tree[root].sta = false; 57 return x; 58 } 59 int main () 60 { 61 int t; 62 scanf ("%d", &t); 63 while (t --) 64 { 65 int n, num = 0; 66 scanf ("%d", &n); 67 for (int i=0; i<n; i++) 68 { 69 scanf ("%d %d", &pos[i].l, &pos[i].r); 70 x[num++] = pos[i].l; 71 x[num++] = pos[i].r; 72 } 73 sort(x, x+num); 74 num = unique(x, x+num) - x; 75 memset (hash, 0, sizeof(hash)); 76 int nu = 0; 77 for (int i=0; i<num; i++) 78 { 79 hash[x[i]] = nu; 80 if (i < num - 1) 81 { 82 if (x[i+1] - x[i] == 1) 83 nu ++; 84 else 85 nu += 2; 86 } 87 } 88 Build(0, 0, nu); 89 int sum = 0; 90 for (int i=n-1; i>=0; i--) 91 sum += update (0, hash[pos[i].l], hash[pos[i].r]); 92 printf ("%d ", sum); 93 } 94 return 0; 95 }