【bzoj1818】[Cqoi2010]内部白点

来源:互联网 发布:中信期货软件 编辑:程序博客网 时间:2024/06/08 09:31
#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;}

0 0
原创粉丝点击