PKU 2528 - Mayor's posters(线段树)

思路

线段树学习第三发

引用一下NotOnlySuccess大大的思路。

离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了 
所以离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多 
而这题的难点在于每个数字其实表示的是一个单位长度(并非一个点),这样普通的离散化会造成许多错误(包括我以前的代码,poj这题数据奇弱) 
给出下面两个简单的例子应该能体现普通离散化的缺陷: 
例子一:1-10 1-4 5-10 
例子二:1-10 1-4 6-10 
普通离散化后都变成了[1,4][1,2][3,4] 
线段2覆盖了[1,2],线段3覆盖了[3,4],那么线段1是否被完全覆盖掉了呢? 
例子一是完全被覆盖掉了,而例子二没有被覆盖 
为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10] 
如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了. 
线段树功能:update:成段替换 query:简单hash

因为可能有2W个点,每个点又都可能插入一个数据,所以要开到4W * 4W个结点。

当你看到其他解题报告是8W个结点的时候,那他一定是错的。

(为了探究这8W和16W整页VJ都被我刷满了╮(╯▽╰)╭)

代码

  
  
  
  
  1. #include <cstdio>
  2. #include <stack>
  3. #include <set>
  4. #include <iostream>
  5. #include <string>
  6. #include <vector>
  7. #include <queue>
  8. #include <functional>
  9. #include <cstring>
  10. #include <algorithm>
  11. #include <cctype>
  12. #include <ctime>
  13. #include <cstdlib>
  14. #include <fstream>
  15. #include <string>
  16. #include <sstream>
  17. #include <map>
  18. #include <cmath>
  19. #define LL long long
  20. #define Lowbit(x) ((x) & (-x))
  21. #define MP(a, b) make_pair(a, b)
  22. #define MS(arr, num) memset(arr, num, sizeof(arr))
  23. #define PB push_back
  24. #define F first
  25. #define S second
  26. #define ROP freopen("input.txt", "r", stdin);
  27. #define MID(a, b) (a + ((b - a) >> 1))
  28. #define LC rt << 1, l, mid
  29. #define RC rt << 1|1, mid + 1, r
  30. #define LRT rt << 1
  31. #define RRT rt << 1|1
  32. #define BitCount(x) __builtin_popcount(x)
  33. const double PI = acos(-1.0);
  34. const int INF = 0x3f3f3f3f;
  35. using namespace std;
  36. const int MAXN = 2e4 + 5;
  37. const int MOD = 20071027;
  38. typedef pair<int, int> pii;
  39. typedef vector<int>::iterator viti;
  40. typedef vector<pii>::iterator vitii;
  41. struct POINT
  42. {
  43. int l, r;
  44. }pit[10005];
  45. int ans, col[20000 << 3];
  46. set<int> mp;
  47. vector<int> ve;
  48. void PushDown(int rt)
  49. {
  50. if (col[rt] != -1)
  51. {
  52. col[LRT] = col[RRT] = col[rt];
  53. col[rt] = -1;
  54. }
  55. }
  56. void Query(int rt, int l, int r)
  57. {
  58. if (col[rt] != -1)
  59. {
  60. if (!mp.count(col[rt]))
  61. ans++;
  62. mp.insert(col[rt]);
  63. return;
  64. }
  65. if (l == r) return;
  66. int mid = MID(l, r);
  67. Query(LC);
  68. Query(RC);
  69. }
  70. void Update(int rt, int l, int r, int L, int R, int val)
  71. {
  72. if (L <= l && r <= R)
  73. {
  74. col[rt] = val;
  75. return;
  76. }
  77. PushDown(rt);
  78. int mid = MID(l, r);
  79. if (L <= mid) Update(LC, L, R, val);
  80. if (R > mid) Update(RC, L, R, val);
  81. }
  82. int main()
  83. {
  84. //ROP;
  85. int T, i, j, n;
  86. scanf("%d", &T);
  87. while (T--)
  88. {
  89. ve.clear();
  90. mp.clear();
  91. ans = 0;
  92. scanf("%d", &n);
  93. for (i = 0; i < n; i++)
  94. {
  95. scanf("%d%d", &pit[i].l, &pit[i].r);
  96. ve.PB(pit[i].l); ve.PB(pit[i].r);
  97. }
  98. sort(ve.begin(), ve.end());
  99. int num = unique(ve.begin(), ve.end()) - ve.begin();
  100. ve.resize(num);
  101. int cnt = 0;
  102. for (i = 0; i < num - 1; i++)
  103. if (ve[i] + 1 != ve[i + 1]) ve.PB(ve[i] + 1);
  104. sort(ve.begin(), ve.end());
  105. MS(col, -1);
  106. for (i = 0; i < n; i++)
  107. {
  108. int l = lower_bound(ve.begin(), ve.end(), pit[i].l) - ve.begin();
  109. int r = lower_bound(ve.begin(), ve.end(), pit[i].r) - ve.begin();
  110. Update(1, 0, ve.size() - 1, l, r, i);
  111. }
  112. Query(1, 0, ve.size() - 1);
  113. printf("%d\n", ans);
  114. }
  115. return 0;
  116. }

你可能感兴趣的:(ACM)