zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    热爱自己的工作
    python 类型转换操作
    使用Python实现Telnet远程登录
    使用Python为程序添加右键菜单打开方式
    【Django实例】序言
    【转】Windows右键菜单设置与应用技巧
    【转】浅谈以太网帧格式
    Beyond Compare脚本:比较文件并生成html格式的差异报告
    【转】C语言中的位域、字节序、比特序、大小端
    【转】tcpdump抓取TCP/IP数据包分析
  • 原文地址:https://www.cnblogs.com/storz/p/10191309.html
Copyright © 2011-2022 走看看