题解
首先,题目有一个不好的引导,即求每一种的集合大小的个数,然后自闭…
转换思维,枚举所有的 y坐标,求可行的 xL和 xR的对数
对于每一个可选择的区域,用最小的 y坐标中的最小的 x坐标区分
对于 xj, xL的范围是 [xj−1+1,xj], xR的范围是 [xj,+∞]
所以我们只需要找到对应区间的 x坐标的个数,相乘加入答案中
反思
一开始想到的区分区域的方法是“最小 x坐标中的最大的 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;
}