把所有点离散化,虚构一根扫描线从上往下扫,每行的点从左往右算贡献,开一个树状数组维护每个离散化后的x坐标是否已经有点
扫描到一个点时,先把这个点更新到树状数组里,每个点的贡献是它左边的所有点数*到它相邻右边点之间的所有点数
#include<bits/stdc++.h> #include<vector> using namespace std; #define maxn 200005 struct Node {int x,y;}p[maxn]; int cmp(Node a,Node b){ if(a.y==b.y)return a.x<b.x; return a.y>b.y; } int n,m; vector<int>x,y; int bit[maxn],f[maxn]; void update(int x){ while(x<=m){ bit[x]++; x+=x&-x; } } int query(int x){ int res=0; while(x){ res+=bit[x]; x-=x&-x; } return res; } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>p[i].x>>p[i].y; x.push_back(p[i].x); } sort(p+1,p+1+n,cmp); sort(x.begin(),x.end()); x.erase(unique(x.begin(),x.end()),x.end()); m=x.size(); long long ans=0; for(int i=1;i<=n;i++){ int pos,R; if(i==n || p[i+1].y!=p[i].y) R=m; else R=lower_bound(x.begin(),x.end(),p[i+1].x)-x.begin()+1-1; pos=lower_bound(x.begin(),x.end(),p[i].x)-x.begin()+1;//p[i]所在位置 if(!f[pos]) update(pos),f[pos]=1; ans+=(long long)query(pos)*(query(R)-query(pos-1)); } cout<<ans<<endl; }