[BZOJ1818][Cqoi2010]内部白点[扫描线]

orz 抄自www.hzwer.com

首先证明不可能出现输出-1的情况:(其实黑点的增长只会发生在第一秒)
反设白点i在第一秒时由于某个方向(设为上方)没有黑点,就没有变成黑点,而在后来又成为了黑点。
此时在i点上方必有了黑点j,而j要成为黑点,j的上方必存在一个黑点,而那个黑点同时也在i的上方,
所以i一开始将成为黑点,矛盾!
那么我们只需求出有多少个整点满足上下左右都存在黑点。

然后先离散化横坐标,将横纵坐标相等的点看做竖线和横线,也就是分别按照点的x,y排序得到所有的线段

然后对所有线段进行排序,从下往上扫描,用树状数组维护区间和

如果碰到一条竖线下端点,将树状数组中其横坐标位置的值+1

碰到一条横线,就询问左端点到右端点并加入答案

如果碰到一条竖线上端点,将树状数组中其横坐标位置的值-1

想完这些我们可以发现,对于一条竖线段,我们可以把它的俩个端点分开和横线一起存入结构体,这样同时可以解决排序的问题

对线段进行排序时,如果y相同,上端点要在最前,下端点在最后

#include <bits/stdc++.h>
using namespace std;
#define read2(a, b) (read(a), read(b))
#define lowbit(x) (x&(-x))
#define getpos(x) (lower_bound(pos+1, pos+1+n, x) - pos)
 
template<class T> void read(T & x) {
  register int c = getchar(), f = 1; x = 0;
  while(!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
  while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
  x *= f;
}
int n, m;
struct Node{
  int x, y;
}N[100007];
struct Seg{
  int l, r, y, k;
}S[300007]; int tot, pos[100007], t[100007];
inline bool cmp1(const Node &a, const Node &b) {return a.y == b.y ? a.x < b.x : a.y < b.y;}
inline bool cmp2(const Node &a, const Node &b) {return a.x == b.x ? a.y < b.y : a.x < b.x;}
inline bool cmp3(const Seg &a, const Seg &b) {return a.y == b.y ? a.k < b.k : a.y < b.y;}
 
inline void add(int x, int v) {
  while(x <= n) t[x] += v, x += lowbit(x);
}
inline int Sum(int x) {
  int ret = 0;
  while(x) ret += t[x], x -= lowbit(x);
  return ret;
}
int main(void) {
  read(n);
  for(int i = 1; i <= n; ++i) read2(N[i].x, N[i].y), pos[i] = N[i].x;
  sort(pos+1, pos+1+n);
  sort(N+1, N+1+n, cmp2);
  for(int i = 2; i <= n; ++i) 
    if (N[i].x == N[i-1].x) 
      S[++tot] = (Seg){getpos(N[i].x), 0, N[i-1].y, 1},
      S[++tot] = (Seg){getpos(N[i].x), 0, N[i].y, -1};
  sort(N+1, N+1+n, cmp1);
  for(int i = 2; i <= n; ++i) 
    if (N[i].y == N[i-1].y)
      S[++tot] = (Seg){getpos(N[i-1].x), getpos(N[i].x), N[i].y, 0};  
  sort(S+1, S+1+tot, cmp3);
  int ans = n;
  for(int i = 1; i <= tot; ++i) {
    if (S[i].k) add(S[i].l, S[i].k);
    else ans += Sum(S[i].r-1) - Sum(S[i].l);
  }
  cout << ans;
  return 0;
}
posted @ 2018-12-28 16:25  QvvQ  阅读(153)  评论(0编辑  收藏  举报