现在的位置: 首页 > 综合 > 正文

【bzoj1818】[Cqoi2010]内部白点

2018年01月13日 ⁄ 综合 ⁄ 共 1573字 ⁄ 字号 评论关闭
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,cnt,ans,hash[100001],tr[100001];//hash储存离散化前的值 
struct point{int x,y;}a[100001];
struct seg{int k,x,y,r;}s[1000001];
//横线时x表示左端点,r表示右端点,y表示纵坐标。 
//竖线时表示点(x,y),k=1表示是下端点,k=-1表示是上端点,r没用。 
inline bool cmp1(point a,point b){
	if(a.x==b.x)return a.y<b.y;
		else return a.x<b.x;
}//将点按x排序 
inline bool cmp2(point a,point b){
	if(a.y==b.y)return a.x<b.x;
		return a.y<b.y;
}//将点按y排序 
inline bool cmp3(seg a,seg b){
    if(a.y==b.y)return a.k<b.k;
    return a.y<b.y;
}//将线按y排序 
int find(int x){//进行离散化处理 
	int l=1,r=n;
	while(l<=r){
		int mid=(l+r)>>1;
		if(hash[mid]<x)l=mid+1;
		else if(hash[mid]>x)r=mid-1;
		else return mid;
	}
}
void insert(int k,int l,int r,int y){
	//k=0时表示插入一条[l,r]的纵坐标为y的横线
	//k=1时表示插入点(find(y),l)和点(find(y),r),表示一条竖线 
	if(!k){
		s[++cnt].x=find(l);s[cnt].r=find(r);s[cnt].y=y;
	}
	else{
		s[++cnt].x=find(y);s[cnt].y=l;s[cnt].k=1;
		s[++cnt].x=find(y);s[cnt].y=r;s[cnt].k=-1;
	}
}
void build(){
	sort(a+1,a+n+1,cmp1);
	for(int i=2;i<=n;i++)
		if(a[i].x==a[i-1].x)//找到一条竖线
			insert(1,a[i-1].y,a[i].y,a[i].x); 
	sort(a+1,a+n+1,cmp2);
	for(int i=2;i<=n;i++)
		if(a[i].y==a[i-1].y)
			insert(0,a[i-1].x,a[i].x,a[i].y);
}
int lowbit(int x){
	return x&(-x);
}
void update(int x,int y){
	while(x<=n){
		tr[x]+=y;
		x+=lowbit(x);
	}
}
int askl(int x){
	int s=0;
	while(x){
		s+=tr[x];
		x-=lowbit(x);
	}
	return s;
}
int ask(int l,int r){
	return askl(r)-askl(l);
}
void work(){
	for(int i=1;i<=cnt;i++){
		if(!s[i].k)ans+=ask(s[i].x,s[i].r);
		else update(s[i].x,s[i].k);
	}
}
void init(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i].x,&a[i].y);
		hash[i]=a[i].x;
	}
	sort(hash+1,hash+n+1);
	build();
	sort(s+1,s+cnt+1,cmp3);
}
int main(){
	init();
	work();
	printf("%d",ans+n);
	return 0;
}

抱歉!评论已关闭.