题目大意:给定平面上的一些黑点,其它位置都是白点,一个白点如果上下左右都有黑点就会变成黑点,求最终会有多少个黑点
语文题?
总之我们现在得到了一些横向和纵向的线段(注意线段不能包含两端点!),求出交点数后+n就是答案
我们可以将横向线段看做修改,纵向线段看做询问,那么一个询问可以拆成两个
然后我们离线做,将询问按y坐标排序,对于每个询问将y坐标小于等于这个询问的修改都加入树状数组,然后查询这个询问的x坐标即可
懒得离散化,第一次尝试用Hash表写树状数组,效果还不错= =
时间复杂度O(nlogn)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
struct Point{
int x,y;
friend istream& operator >> (istream &_,Point &p)
{
scanf("%d%d",&p.x,&p.y);
p.x+=1000000007;
p.y+=1000000007;
return _;
}
}points[M];
struct Interval{
int l,r,y;
Interval() {}
Interval(int _,int __,int ___):
l(_),r(__),y(___) {}
bool operator < (const Interval &i) const
{
return y < i.y;
}
}intervals[M],*I=intervals;
struct Query:Point{
int flag;
Query() {}
Query(int _,int __,int ___):flag(___)
{
x=_;y=__;
}
}queries[M<<1],*Q=queries;
int n;
long long ans;
bool Compare1(const Point &p1,const Point &p2)
{
if(p1.x!=p2.x)
return p1.x<p2.x;
return p1.y<p2.y;
}
bool Compare2(const Point &p1,const Point &p2)
{
if(p1.y!=p2.y)
return p1.y<p2.y;
return p1.x<p2.x;
}
namespace BIT{
struct Hash_Set{
struct List{
int hash,val;
List *next;
List(int _,List *__):
hash(_),val(0),next(__){}
}*head[1001001];
int& operator [] (int hash)
{
int pos=hash%1001001;
List *temp;
for(temp=head[pos];temp;temp=temp->next)
if(temp->hash==hash)
return temp->val;
return (head[pos]=new List(hash,head[pos]))->val;
}
}c;
void Update(int x,int y)
{
for(;x;x-=x&-x)
c[x]+=y;
}
int Get_Ans(long long x)
{
int re=0;
for(;x<=2000000007;x+=x&-x)
re+=c[x];
return re;
}
}
int main()
{
using namespace BIT;
int i;
cin>>n;
for(i=1;i<=n;i++)
cin>>points[i];
sort(points+1,points+n+1,Compare2);
for(i=2;i<=n;i++)
if(points[i].y==points[i-1].y&&points[i].x>=points[i-1].x+2)
new (I++)Interval(points[i-1].x+1,points[i].x-1,points[i].y);
sort(points+1,points+n+1,Compare1);
for(i=2;i<=n;i++)
if(points[i].x==points[i-1].x&&points[i].y>=points[i-1].y+2)
{
new (Q++)Query(points[i].x,points[i-1].y,-1);
new (Q++)Query(points[i].x,points[i].y-1,1);
}
sort(intervals,I);
sort(queries,Q,Compare2);
Interval *_i=intervals;
Query *_q=queries;
for(;_q<Q;_q++)
{
for(;_i<I&&_i->y<=_q->y;_i++)
Update(_i->l-1,-1),Update(_i->r,1);
ans+=Get_Ans(_q->x)*_q->flag;
}
cout<<ans+n<<endl;
return 0;
}