zoukankan      html  css  js  c++  java
  • bzoj1818 [Cqoi2010]内部白点

    Description

    无限大正方形网格里有n个黑色的顶点,所有其他顶点都是白色的(网格的顶点即坐标为整数的点,又称整点)。每秒钟,所有内部白点同时变黑,直到不存在内部白点为止。你的任务是统计最后网格中的黑点个数。 内部白点的定义:一个白色的整点P(x,y)是内部白点当且仅当P在水平线的左边和右边各至少有一个黑点(即存在x1 < x < x2使得(x1,y)和(x2,y)都是黑点),且在竖直线的上边和下边各至少有一个黑点(即存在y1 < y < y2使得(x,y1)和(x,y2)都是黑点)。

    Input

    输入第一行包含一个整数n,即初始黑点个数。以下n行每行包含两个整数(x,y),即一个黑点的坐标。没有两个黑点的坐标相同,坐标的绝对值均不超过109。

    Output

    输出仅一行,包含黑点的最终数目。如果变色过程永不终止,输出-1。

    Sample Input

    4
    0 2
    2 0
    -2 0
    0 -2

    Sample Output

    5
    数据范围
    36%的数据满足:n < = 500
    64%的数据满足:n < = 30000
    100%的数据满足:n < = 100000

    正解:扫描线+树状数组。

    容易发现,如果一个白点的上下左右都有黑点,那么它就能变成白点。

    所以点是可以直接离散化的,无数点的情况也是没有的。

    于是直接写一个扫描线,扫描每一列,然后用树状数组统计每一行是否上下都有黑点就行了。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define lb(x) (x & -x)
     6 #define inf (1<<30)
     7 #define N (100005)
     8 
     9 using namespace std;
    10 
    11 struct point{ int x,y; }p[N];
    12 
    13 vector<int> g[N];
    14 int hsh[N],num[N],cnt[N],can[N],c[N],mn[N],mx[N],n,tot;
    15 ll ans;
    16 
    17 il int gi(){
    18   RG int x=0,q=1; RG char ch=getchar();
    19   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    20   if (ch=='-') q=-1,ch=getchar();
    21   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    22   return q*x;
    23 }
    24 
    25 il void add(RG int x,RG int v){
    26   for (;x<=n;x+=lb(x)) c[x]+=v; return;
    27 }
    28 
    29 il int query(RG int x){
    30   RG int res=0;
    31   for (;x;x^=lb(x)) res+=c[x]; return res;
    32 }
    33 
    34 int main(){
    35 #ifndef ONLINE_JUDGE
    36   freopen("white.in","r",stdin);
    37   freopen("white.out","w",stdout);
    38 #endif
    39   n=gi();
    40   for (RG int i=1;i<=n;++i) hsh[++tot]=p[i].x=gi(),p[i].y=gi();
    41   sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1;
    42   for (RG int i=1;i<=n;++i) p[i].x=lower_bound(hsh+1,hsh+tot+1,p[i].x)-hsh;
    43   for (RG int i=1;i<=n;++i) mn[i]=inf,mx[i]=0;
    44   tot=0; for (RG int i=1;i<=n;++i) hsh[++tot]=p[i].y;
    45   sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1;
    46   for (RG int i=1;i<=n;++i) p[i].y=lower_bound(hsh+1,hsh+tot+1,p[i].y)-hsh;
    47   for (RG int i=1;i<=n;++i){
    48     g[p[i].x].push_back(i),++cnt[p[i].y];
    49     mn[p[i].x]=min(mn[p[i].x],p[i].y),mx[p[i].x]=max(mx[p[i].x],p[i].y);
    50   }
    51   for (RG int i=1;i<=n;++i){
    52     if (mn[i]>mx[i]) continue;
    53     for (RG int j=0,k;j<g[i].size();++j){
    54       k=p[g[i][j]].y,++num[k];
    55       if (can[k]!=(num[k]&&cnt[k])) add(k,1),can[k]=1;
    56     }
    57     if (mn[i]!=mx[i]) ans+=query(mx[i]-1)-query(mn[i])+2; else ++ans;
    58     for (RG int j=0,k;j<g[i].size();++j){
    59       k=p[g[i][j]].y,--cnt[k];
    60       if (can[k]!=(num[k]&&cnt[k])) add(k,-1),can[k]=0;
    61     }
    62   }
    63   cout<<ans; return 0;
    64 }
  • 相关阅读:
    linux命令:ls
    linux 进程线程拓展
    linux命令:find
    电动车充电器原理及带电路图维修
    kmalloc分配物理内存与高端内存映射--Linux内存管理(十八)
    Linux内核最新的连续内存分配器(CMA)——避免预留大块内存【转】
    alloc_page分配内存空间--Linux内存管理(十七)
    伙伴系统之避免碎片--Linux内存管理(十六)
    伙伴系统之伙伴系统概述--Linux内存管理(十五)
    USB初学(一)---USB-HID的初步认识【转】
  • 原文地址:https://www.cnblogs.com/wfj2048/p/8001276.html
Copyright © 2011-2022 走看看