题解

首先,题目有一个不好的引导,即求每一种的集合大小的个数,然后自闭…
转换思维,枚举所有的 y y y坐标,求可行的 x L x_L xL x R x_R xR的对数
对于每一个可选择的区域,用最小的 y y y坐标中的最小的 x x x坐标区分
对于 x j x_j xj x L x_L xL的范围是 [ x j 1 + 1 , x j ] [x_{j-1}+1,x_j] [xj1+1,xj] x R x_R xR的范围是 [ x j , + ] [x_j,+\infty] [xj,+]
所以我们只需要找到对应区间的 x x x坐标的个数,相乘加入答案中

反思

一开始想到的区分区域的方法是“最小 x x x坐标中的最大的 y y y”,然后分别统计各种集合大小的个数,完全跑偏了

题目中区域的是向上无穷大的,所以应该利用这一特性,用 y y y来划分,就能保证后面的能包含前面的点

代码

#include<bits/stdc++.h>
#define N 300010
#define INF 0x3f3f3f3f
#define eps 1e-10
#define pi 3.141592653589793
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rbtree;
rbtree q;
map<int, vector<int> > mp;

int main()
{
    int n;sc(n);
    for (int i=1;i<=n;i++){
        int x,y;
        scc(x,y);
        mp[y].pb(x);
    }
    LL ans=0;
    for (auto y:mp){
        sort(y.se.begin(), y.se.end());
        for(auto x:y.se) q.insert(x);
        int tm=0,qs=q.size();
        for (auto x:y.se) {
            int t=q.order_of_key(x+1);
            ans+=(LL)(t-tm)*(qs-t+1);
            tm=t;
        }
    }
    cout<<ans;
    return 0;
}