1. 程式人生 > >bzoj 1818 [CQOI 2010] 內部白點 - 掃描線 - 樹狀數組

bzoj 1818 [CQOI 2010] 內部白點 - 掃描線 - 樹狀數組

accept memcpy eof define border lan lin http tps

題目傳送門

  快速的列車

  慢速的列車

題目大意

  一個無限大的方格圖內有$n$個黑點。問有多少個位置上下左右至少有一個黑點或本來是黑點。

  掃描線是顯然的。

  考慮一下橫著的線段,取它兩個端點,橫坐標小的地方放一個+1,大的地方放一個-1事件。

  然後掃描,掃到的橫著的線段更新,豎著的線段用樹狀數組求答案。

  然後考慮這一列上原來存在的黑點有沒有被統計,如果沒有就加上。

Code

  1 /**
  2  * bzoj
  3  * Problem#1818
  4  * Accepted
  5  * Time: 1824ms
  6
* Memory: 9776k 7 */ 8 #include <algorithm> 9 #include <iostream> 10 #include <cstdlib> 11 #include <cstring> 12 #include <cstdio> 13 #include <vector> 14 #ifndef WIN32 15 #define Auto "%lld" 16 #else 17 #define Auto "%I64d" 18 #endif 19
using namespace std; 20 #define smax(a, b) (a = max(a, b)) 21 #define smin(a, b) (a = min(a, b)) 22 typedef bool boolean; 23 #define ll long long 24 25 const int N = 1e5 + 5; 26 27 typedef class IndexedTree { 28 public: 29 int s; 30 int* ar; 31 32
IndexedTree() { } 33 IndexedTree(int s):s(s) { 34 ar = new int[(s + 1)]; 35 memset(ar, 0, sizeof(int) * (s + 1)); 36 } 37 38 void add(int idx, int val) { 39 for ( ; idx <= s; idx += (idx & (-idx))) 40 ar[idx] += val; 41 } 42 43 int query(int idx) { 44 int rt = 0; 45 for ( ; idx; idx -= (idx & (-idx))) 46 rt += ar[idx]; 47 return rt; 48 } 49 }IndexedTree; 50 51 typedef class Event { 52 public: 53 int x, y, val; 54 55 Event(int x = 0, int y = 0, int val = 0):x(x), y(y), val(val) { } 56 57 boolean operator < (Event b) const { 58 return x < b.x; 59 } 60 }Event; 61 62 int n; 63 int xs[N], ys[N], bxs[N], bys[N]; 64 int ls[N], rs[N], us[N], ds[N]; 65 ll res = 0; 66 int tp = 0; 67 Event es[N << 1]; 68 vector<int> vs[N]; 69 IndexedTree it; 70 71 inline void init() { 72 scanf("%d", &n); 73 for (int i = 1; i <= n; i++) 74 scanf("%d%d", xs + i, ys + i); 75 } 76 77 inline void descrete(int* ar, int* br, int n) { 78 memcpy(br, ar, sizeof(int) * (n + 1)); 79 sort(br + 1, br + n + 1); 80 for (int i = 1; i <= n; i++) 81 ar[i] = lower_bound(br + 1, br + n + 1, ar[i]) - br; 82 } 83 84 inline void solve() { 85 descrete(xs, bxs, n); 86 descrete(ys, bys, n); 87 88 for (int i = 1; i <= n; i++) 89 ls[i] = ds[i] = N; 90 for (int i = 1; i <= n; i++) 91 us[i] = rs[i] = 0; 92 93 for (int i = 1; i <= n; i++) { 94 smin(ls[ys[i]], xs[i]); 95 smax(rs[ys[i]], xs[i]); 96 smin(ds[xs[i]], ys[i]); 97 smax(us[xs[i]], ys[i]); 98 } 99 100 for (int i = 1; i <= n; i++) 101 vs[xs[i]].push_back(ys[i]); 102 103 for (int i = 1; i <= n; i++) 104 if (ls[i] < rs[i] - 1) { 105 es[++tp] = Event(ls[i], i, 1); 106 es[++tp] = Event(rs[i], i, -1); 107 } 108 sort(es + 1, es + tp + 1); 109 110 int pe = 1; 111 it = IndexedTree(n); 112 bxs[0] = -1e9 - 5; 113 for (int i = 1; i <= n; i++) { 114 if (bxs[i] == bxs[i - 1]) continue; 115 while (pe <= tp && es[pe].x == i) 116 it.add(es[pe].y, es[pe].val), pe++; 117 if (ds[i] <= us[i]) 118 res += it.query(us[i]) - it.query(ds[i] - 1);//, cerr << bxs[i] << endl; 119 for (int j = 0; j < (signed) vs[i].size(); j++) 120 if (it.query(vs[i][j]) - it.query(vs[i][j] - 1) == 0) 121 res++; 122 // cerr << bxs[i] << " " << res << endl; 123 } 124 printf(Auto"\n", res); 125 } 126 127 int main() { 128 init(); 129 solve(); 130 return 0; 131 }

bzoj 1818 [CQOI 2010] 內部白點 - 掃描線 - 樹狀數組