分治。
1.按y轴排序
2.分治处理(l,mid)和(mid+1,r),计算(l,mid)能对(mid+1,r)部分作出的贡献
随便花一个图发现上半部分维护y值递增的单调栈下半部分维护y单调减得单调栈,这样下半部分栈中元素都是可以和上半部分配对不会出现包括的情况,但是x坐标必须大于s1[t1-1]就是第一个上半部分比当前枚举的这个坐标的y坐标小的坐标的x值大。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 200021
using namespace std;
int n,s1[maxn],s2[maxn],t1,t2;
long long ans;
struct data{
int x,y;
bool operator<(const data& b)const{return y<b.y;}
}a[maxn],t[maxn];
void update(){
int x=a[s1[t1-1]].x;//找到单调栈中x大于等于x的
int l=0,r=t2;
while(l<r){
int mid=l+r+1>>1;
if(a[s2[mid]].x>=x)r=mid-1;
else l=mid;
}ans+=(long long)t2-l;
}
void solve(int l,int r){
if(l==r)return ;
int mid=l+r>>1;
solve(l,mid),solve(mid+1,r);
t1=t2=0;
for(int j=l,i=mid+1;i<=r;i++){
while(t1&&a[i].y<=a[s1[t1]].y)t1--;
s1[++t1]=i;
for(;j<=mid&&a[j].x<a[i].x;j++){
while(t2&&a[j].y>=a[s2[t2]].y )t2--;
s2[++t2]=j;
}
update();
}
int p1=l,p2=mid+1;
for(int i=l;i<=r;i++){
if((a[p1].x<=a[p2].x&&p1<=mid)||p2>r)t[i]=a[p1++];
else t[i]=a[p2++];
}
for(int i=l;i<=r;i++)a[i]=t[i];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+1+n);
solve(1,n);cout<<ans;
return 0;
}