bzoj1818: [Cqoi2010]内部白点

来源:互联网 发布:航拍测绘软件 编辑:程序博客网 时间:2024/06/08 19:04

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

我们发现,其实新变成的点是没有任何*用的
反正大概就是有很多线段,求一下交点什么的。。
这个的话扫一下,用个线段树维护一下就好了

具体看代码,不想写了

#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>using namespace std;const int N=100005*2;int n;struct qq{    int x,y;    int tx,ty;}s[N];int X1[N],X2[N];//表示X坐标是这时的最小和最大int Y1[N],Y2[N];//表示Y坐标是这时的最小和最大bool cmp (qq a,qq b){return a.x<b.x;}bool cmp1 (qq a,qq b){return a.y<b.y;}int XX,YY;void init (){    scanf("%d",&n);    for (int u=1;u<=n;u++)        scanf("%d%d",&s[u].x,&s[u].y);}void prepare (){    memset(X1,127,sizeof(X1));memset(X2,0,sizeof(X2));    memset(Y1,127,sizeof(Y1));memset(Y2,0,sizeof(Y2));    sort(s+1,s+1+n,cmp);    s[1].tx=1;    for (int u=2;u<=n;u++)    {        s[u].tx=s[u-1].tx;        if (s[u].x!=s[u-1].x) s[u].tx++;    }XX=s[n].tx;    sort(s+1,s+1+n,cmp1);    s[1].ty=1;    for (int u=2;u<=n;u++)    {        s[u].ty=s[u-1].ty;        if (s[u].y!=s[u-1].y) s[u].ty++;    }YY=s[n].ty;    for (int u=1;u<=n;u++)     {        X1[s[u].tx]=min(X1[s[u].tx],s[u].ty),X2[s[u].tx]=max(X2[s[u].tx],s[u].ty);        Y1[s[u].ty]=min(Y1[s[u].ty],s[u].tx),Y2[s[u].ty]=max(Y2[s[u].ty],s[u].tx);    }/*  printf("\n");    for (int u=1;u<=n;u++) printf("%d %d\n",s[u].tx,s[u].ty);    printf("\n");    for (int u=1;u<=XX;u++) printf("%d %d\n",X1[u],X2[u]);    printf("\n");    for (int u=1;u<=YY;u++) printf("%d %d\n",Y1[u],Y2[u]);    printf("\n");*/}struct qy{    int x,y;    int z;}a[N];int cnt=0;struct qa{    int l,r;    int s1,s2;    int c;}tr[N*2];int num=0;bool cmp2 (qy x,qy y){return x.x<y.x;}void bt (int l,int r){    int a=++num;    tr[a].l=l;tr[a].r=r;    tr[a].c=0;    if (l==r)   return ;    int mid=(l+r)>>1;    tr[a].s1=num+1;bt(l,mid);    tr[a].s2=num+1;bt(mid+1,r);}void update (int now){    if (tr[now].c==0) return ;    int s1=tr[now].s1,s2=tr[now].s2;    tr[s1].c+=tr[now].c;    tr[s2].c+=tr[now].c;    tr[now].c=0;}void change (int now,int l,int r){    if (tr[now].l==l&&tr[now].r==r) {tr[now].c++;return ;}    update(now);    int s1=tr[now].s1,s2=tr[now].s2;    int mid=(tr[now].l+tr[now].r)>>1;    if (r<=mid) change(s1,l,r);    else if (l>mid) change(s2,l,r);    else change(s1,l,mid),change(s2,mid+1,r);}int get (int now,int x){    if (tr[now].l==tr[now].r)        return tr[now].c;    update(now);    int s1=tr[now].s1,s2=tr[now].s2;    int mid=(tr[now].l+tr[now].r)>>1;    if (x<=mid) return get(s1,x);    else return get(s2,x);}void solve (){    int ans=0;    for (int u=1;u<=YY;u++)    {        a[++cnt].x=Y1[u]-1;        a[cnt].y=u;        a[cnt].z=-1;        a[++cnt].x=Y2[u];        a[cnt].y=u;        a[cnt].z=1;    }    sort(a+1,a+1+cnt,cmp2);    /*for (int u=1;u<=cnt;u++)        printf("%d %d %d\n",a[u].x,a[u].y,a[u].z);*/    bt(1,YY);    int i=0;    for (int u=1;u<=cnt;u++)    {        while (i+1<=a[u].x)        {            i++;            change(1,X1[i],X2[i]);        }        ans=ans+a[u].z*get(1,a[u].y);    }    printf("%d\n",ans);}int main(){    init();    prepare();    solve();    return 0;}
原创粉丝点击