传送门
首先没有-1的情况(十分显然)。
于是答案就是线段交点个数。
我们可以1求出所有横线竖线,共2*n条。
然后我们按照棱线扫描,竖线在树状数组上维护。
xjb乱搞以下就可以了。
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
struct point{int x,y;}a[N];
struct edge{int k,x,y,r;}s[N*3];
int n,cnt,ans,hash[N],b[N];
bool cmp1(point a,point b){
if (a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
bool cmp2(point a,point b){
if (a.y==b.y) return a.x<b.x;
return a.y<b.y;
}
bool cmp3(edge a,edge b){
if (a.y==b.y) return a.k<b.k;
return a.y<b.y;
}
int ef(int x){
int l=1,r=n,mid;
while (l<=r){
mid=(l+r)>>1;
if (hash[mid]==x) return mid;
else if (hash[mid]>x) r=mid-1; else l=mid+1;
};
}
void ins(int k,int l,int r,int t){
if (!k){
s[++cnt].x=ef(l);
s[cnt].r=ef(r);
s[cnt].y=t;
}
else{
s[++cnt].x=ef(t);
s[cnt].y=l;
s[cnt].k=1;
s[++cnt].x=ef(t);
s[cnt].y=r;
s[cnt].k=-1;
}
}
void change(int x,int y){
for (;x<=n;x+=x&(-x)) b[x]+=y;
}
int ask(int x){
int s=0;
for (;x>0;x-=x&(-x)) s+=b[x];
return s;
}
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+n+1);
sort(a+1,a+n+1,cmp1);
for (int i=2;i<=n;i++) if (a[i].x==a[i-1].x) ins(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) ins(0,a[i-1].x,a[i].x,a[i].y);
sort(s+1,s+cnt+1,cmp3);
for (int i=1;i<=cnt;i++)
if (!s[i].k) ans+=ask(s[i].r-1)-ask(s[i].x);
else change(s[i].x,s[i].k);
printf("%d",ans+n);
}