[Cqoi2010]内部白点

[Cqoi2010]内部白点

Time Limit:10000MS Memory Limit:65536K
Total Submit:63 Accepted:32
Case Time Limit:2000MS

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

Sample Output

Source
注意到每个黑点只要当前不能被染黑以后也不会被染黑。。就OK了。。
只要弄个扫描线搞一下,再用树状数组维护部分和就OK了
详情见代码吧。。
Code:
#include <vector>

#include <algorithm>
#include <utility>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <map>
#include <cstring>
#include <set>
#define rep(i,n) for(int i=0;i<n;i++)
#define pb push_back
#define Debug(x) cout<<#x<<"="<<x<<endl;
#define For(i,l,r) for(int i=l;i<=r;i++)
#define All(x) x.begin(),x.end()
const int inf=~0U>>1,maxn=100000;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int n;
struct Index
{
    int A[maxn],n;
    Index(){n=0;}
    void Add(int x){A[n++]=x;}
    void DoIt()
    {
        sort(A,A+n);
        n=unique(A,A+n)-A;
    }
    int operator[](int v)
    {
        return lower_bound(A,A+n,v)-A;
    }
}IndexY;
struct TreeArray
{
    int A[maxn],n;
    TreeArray()
    {
        memset(A,0,sizeof A);
    }
    void SetN(int _n){n=_n;}
    void Add(int x,int d)
    {
        for(x++;x<=n;x+=x&-x)
            A[x-1]+=d;
    }
    int Sum(int x)
    {
        int ret=0;
        for(x++;x;x-=x&-x)
            ret+=A[x-1];
        return ret;
    }
}TA;
map<int,vector<int> > Ps;
typedef map<int,vector<int> >::iterator mit;
int Left[maxn]={},Right[maxn]={};
void Init()
{
    scanf("%d",&n);int x,y;
    rep(i,n)
    {
        scanf("%d%d",&x,&y);
        Ps[x].pb(y);
        IndexY.Add(y);
    }
    IndexY.DoIt();
    for(mit it=Ps.begin();it!=Ps.end();it++)
    {
        vector<int>&V=it->second;
        rep(i,V.size())V[i]=IndexY[V[i]],Right[V[i]]++;
        sort(All(V));
    }
}
#define OK(x) (Left[x]&&Right[x])
inline void Update(int x,int d)
{
    int s=OK(x);
    if(d==1)Left[x]++;
    else Right[x]–;
    TA.Add(x,OK(x)-s);
}
void Solve()
{
    ll ans=0;
    TA.SetN(IndexY.n);
    for(mit it=Ps.begin();it!=Ps.end();it++)
    {
        vector<int>&V=it->second;
        int n=V.size();
        rep(i,n)Update(V[i],-1);
        ans+=TA.Sum(V[n-1])-TA.Sum(V[0]-1);
        rep(i,n)ans-=OK(V[i]);
        rep(i,n)Update(V[i],1);
    }
    cout<<ans+n<<endl;
}
int main()
{
    //freopen("in","r",stdin);
    Init();
    Solve();
}

5数据范围36%的数据满足:n < = 50064%的数据满足:n < = 30000100%的数据满足:n < = 10000040 22 0-2 00 -2

3 thoughts on “[Cqoi2010]内部白点

Leave a Reply to 有一点悲剧 Cancel reply

Your email address will not be published. Required fields are marked *