poj 3109 Inner Vertices(树状数组)

Inner Vertices
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 1692 Accepted: 446
Case Time Limit: 2000MS

Description

There is an infinite square grid. Some vertices of the grid are black and other vertices are white.

A vertex V is called inner if it is both vertical-inner and horizontal-inner. A vertex V is called horizontal-inner if there are two such black vertices in the same row that V is located between them. A vertex V is called vertical-inner if there are two such black vertices in the same column that V is located between them.

On each step all white inner vertices became black while the other vertices preserve their colors. The process stops when all the inner vertices are black.

Write a program that calculates a number of black vertices after the process stops.

Input

The first line of the input file contains one integer number n (0 ≤ n ≤ 100 000) — number of black vertices at the beginning.

The following n lines contain two integer numbers each — the coordinates of different black vertices. The coordinates do not exceed 109 by their absolute values.

Output

Output the number of black vertices when the process stops. If the process does not stop, output -1.

Sample Input

4
0 2
2 0
-2 0
0 -2

Sample Output

5

Hint


看了一天多的别人的代码:http://blog.csdn.net/z309241990/article/details/38638243,太弱了

预处理标记第i个点是最上面的还是最下面的点,如果是最下面的点且不是最下面的点,就增加一列被染色的点,

如果是最上面的点且不是最下方的点,肯定少一列被染色的点,最后以y坐标为扫描线,看这段区间有几列被染

色。

代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=200000+100;
struct node
{
    int x;
    int y;
}p[maxn];
int a[maxn];
int b[maxn];
int n,cur;
bool vis[maxn],l[maxn],r[maxn];
bool cmp(node u,node v)
{
    if(u.y==v.y)
        return u.x<v.x;
    return u.y<v.y;
}
int low(int k)
{
    return k&(-k);
}
void update(int k,int v)
{
    while(k<maxn)
    {
        a[k]+=v;
        k+=low(k);
    }
}
long long sum(int k)
{
    long long ans=0;
    while(k>0)
    {
        ans+=a[k];
        k-=low(k);
    }
    return ans;
}
void init()//预处理
{
    memset(a,0,sizeof(a));//初始化树状数组
    sort(b,b+cur);
    cur=unique(b,b+cur)-b;//排序,离散化
    for(int i=0;i<n;i++)
    {
        p[i].x=lower_bound(b,b+cur,p[i].x)-b+1;
        p[i].y=lower_bound(b,b+cur,p[i].y)-b+1;
    }
    sort(p,p+n,cmp);//按y排序,已y坐标建扫描线
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++)
    {
       if(!vis[p[i].x])//预处理,k位置在下方第一次出现
       {
           l[i]=1;
           vis[p[i].x]=1;
       }
       else
       l[i]=0;
    }
    memset(vis,0,sizeof(vis));
    for(int i=n-1;i>=0;i--)
    {
        if(!vis[p[i].x])//第k个点的x坐标在上方出现第一次出现
        {
            r[i]=1;
            vis[p[i].x]=1;
        }
        else
        r[i]=0;
    }
}
void solve()
{
    long long ans=0;
    for(int i=0;i<n;)
    {
        int j=i;
       while(j<n-1&&p[j].y==p[j+1].y)//同一条扫描线
       j++;
       for(int k=i;k<=j;k++)
       {
           if(!l[k]&&r[k])// 最上面的点,且下面存在被染色的点
           {
               update(p[k].x,-1);
           }
       }
       if(i!=j)
       ans+=(sum(p[j].x-1)-sum(p[i].x));//p[j].x-1到p[i].x间被改变颜色的点
       if(i<j)
       {
           for(int k=i+1;k<j;k++)
           if(!l[k]&&!r[k])//原来是黑色的点
           ans--;
       }
       while(i<=j)
       {
           if(l[i]&&!r[i])//p[i].x是最底下的位置,且上面有元素,p[i].x上的要被染色
           update(p[i].x,1);
           i++;
       }
    }
    printf("%I64d\n",ans+n);
}
int main()
{
    while(~scanf("%d",&n))
    {
        cur=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            b[cur++]=p[i].x;
            b[cur++]=p[i].y;
        }
        init();
        solve();
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值