1818: [Cqoi2010]内部白点

题目真坑。。。。。。。。明显不可能会出现-1的情况嘛

离散化+树状数组

x,y坐标分别排序,扫一遍,找出所有的横线和竖线,统计出横线、竖线上端点、竖线下端点。

对统计出的数据进行排序,关键字为y,当y值相同时,下端点优先于横线优先于上端点。

从上往下依次扫描,扫到横线时统计横线左右端点内(开区间)的竖线数量,扫到竖线上端点时竖线数量+1,扫到下端点时竖线数量-1(上边的优先级因此确立)。

最后由于没有统计原先存在的黑点,再加上即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+5;
struct Node{
	int x,y;
}a[N];
struct Segment{
	int l,r,y,k;									//k=0 横线,k=1 竖线上端点,k=-1 竖线下端点 
}s[N*3];
int hash[N],tr[N],n,cnt,ans;
int gethash(int x){
	return lower_bound(hash+1,hash+1+n,x)-hash;
}
bool cmp1(Node a,Node b){							//横线统计 
	if(a.y!=b.y)return a.y<b.y;
	return a.x<b.x;
}
bool cmp2(Node a,Node b){							//竖线统计 
	if(a.x!=b.x)return a.x<b.x;
	return a.y<b.y;
}
bool cmp3(Segment a,Segment b){
	if(a.y!=b.y)return a.y<b.y;
	return a.k<b.k;
}
void pre(){
	sort(a+1,a+1+n,cmp1);
	for(int i=2;i<=n;i++)
	if(a[i].y==a[i-1].y){
		s[++cnt].l=gethash(a[i-1].x);s[cnt].r=gethash(a[i].x);s[cnt].y=a[i].y;s[cnt].k=0;
	}
	sort(a+1,a+1+n,cmp2);
	for(int i=2;i<=n;i++)
	if(a[i].x==a[i-1].x){
		int tmp=gethash(a[i].x);
		s[++cnt].y=a[i-1].y;s[cnt].l=tmp;s[cnt].k=1;
		s[++cnt].y=a[i].y;s[cnt].l=tmp;s[cnt].k=-1;
	}
}
inline int lowbit(int x){return x&-x;}
void add(int x,int v){
	for(;x<=n;x+=lowbit(x))tr[x]+=v;
}
int sum(int x){
	int ret=0;
	for(;x>0;x-=lowbit(x))ret+=tr[x];
	return ret;
}
void go(){
	for(int i=1;i<=cnt;i++)
	if(s[i].k)add(s[i].l,s[i].k);
	else ans+=sum(s[i].r-1)-sum(s[i].l);
}
int main(){
	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+1+n);
	pre();
	sort(s+1,s+1+cnt,cmp3);
	go();
	printf("%d",ans+n);
	return 0;
}
	


你可能感兴趣的:(1818: [Cqoi2010]内部白点)