bzoj 1818 [CQOI 2010] 内部白点 - 扫描线 - 树状数组

Posted yyf0309

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1818 [CQOI 2010] 内部白点 - 扫描线 - 树状数组相关的知识,希望对你有一定的参考价值。

题目传送门

  快速的列车

  慢速的列车

题目大意

  一个无限大的方格图内有$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"
", res);
125 }
126 
127 int main() {
128     init();
129     solve();
130     return 0;
131 }

 

以上是关于bzoj 1818 [CQOI 2010] 内部白点 - 扫描线 - 树状数组的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1818[Cqoi2010]内部白点 扫描线+树状数组

BZOJ 1818: [Cqoi2010]内部白点

bzoj 1818: [Cqoi2010]内部白点

bzoj 1818 [CQOI 2010] 内部白点 - 扫描线 - 树状数组

1818: [Cqoi2010]内部白点

1818: [Cqoi2010]内部白点