分治的时候我们只需要右上点在右半个,左下点在左半个即可,然后左边每个点可以用set求出它所能贡献的y的区间,对于右半边可以求出他能取到的区间,然后排个序用two points+树状数组维护一下即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include<set>
#include<queue>
using namespace std;
typedef pair<int,int>p1;
const int maxn=200005;
struct pi{
int x,y;
}pp[maxn],pp1[maxn],pp2[maxn];
typedef long long LL;
LL ans;
int y[maxn];
int bit[maxn];
int low(int p){
return p&(-p);
}
void merg(int p,int n,int k){
while (p<=n) {
bit[p]+=k;
p=p+low(p);
}
}
int sum(int p){
int s=0;
while(p){
s+=bit[p];
p=p-low(p);
}
return s;
}
set<int>ss;
int cmp(pi a,pi b){
return a.x<b.x;
}
int cmp1(pi a,pi b){
return a.y<b.y;
}
int all[maxn];
int n;
void divide(int l,int r){
if(l==r) return;
int mid=(l+r)/2;
divide(l,mid);
divide(mid+1,r);
ss.clear();
ss.insert(n+1);
int tot=0;
for(int i=mid;i>=l;i--){
set<int>::iterator it;
it=ss.lower_bound(pp[i].y);
pp1[tot].x=pp[i].y;
pp1[tot].y=*it;
tot++;
ss.insert(pp[i].y);
}
ss.clear();
ss.insert(0);
int cnt=0;
for(int i=mid+1;i<=r;i++){
set<int>::iterator it;
it=ss.lower_bound(pp[i].y);
it--;
pp2[cnt].x=*it;
pp2[cnt].y=pp[i].y;
cnt++;
ss.insert(pp[i].y);
}
sort(pp1,pp1+tot,cmp1);
sort(pp2,pp2+cnt,cmp1);
for(int i=0;i<tot;i++) merg(pp1[i].x,n,1);
int p=0;
for(int i=0;i<cnt;i++){
while(p<tot&&pp1[p].y<=pp2[i].y){
merg(pp1[p].x,n,-1);
p++;
}
ans+=sum(pp2[i].y)-sum(pp2[i].x);
}
while (p<tot) {
merg(pp1[p].x,n,-1);
p++;
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d%d",&pp[i].x,&pp[i].y);
y[i]=pp[i].y;
}
sort(y+1,y+1+n);
for(int i=1;i<=n;i++){
pp[i].y=lower_bound(y+1,y+1+n,pp[i].y)-y;
}
sort(pp+1,pp+1+n,cmp);
ans=0;
divide(1,n);
cout<<ans<<endl;
}