When test driving a vehicle, you are asked to make a checkmark on a tablet. Upon inspection, you have noticed many fingerprints on the screen. Aside from the rush of disgust, you notice that the fingerprints on the screen can be represented by a series of 2D points on a standard Cartesian grid. You know that checkmarks can be uniquely defined by three points; these three points have distinct x coordinates and the three points also have distinct y coordinates. The leftmost point must be lower than the rightmost point and higher than the middle point. Now you want to know how many unique checkmarks you can make using the 2D points.
Let’s consider some examples. The three points (1,2), (2,1), and (3,2) do not form a valid checkmark because the leftmost and rightmost points are at the same height. The three points (1,2), (2,1), and (2,3) do not form a valid checkmark because two points have the same x coordinates. The three points (1,2), (3,1), and (4,9) do form a valid checkmark.
Given a list of 2D points, determine the number of unique checkmarks that can be formed from them.
输入
The first input line contains a single integer, n (1 ≤ n ≤ 100,000), representing the number of points. Each of the following n input lines contains two integers, xi and yi (1 ≤ xi , yi ≤
1,000,000,000), representing the location of a point on the 2D grid. No two points will be identical.
输出
Print the number of distinct checkmarks that can be formed by the given 2D points.
样例输入 Copy
【样例1】 6 6 6 5 3 1 5 3 2 4 4 2 1 【样例2】 10 4 2 9 4 1 5 2 4 10 5 6 1 3 3 8 3 5 1 7 2
样例输出 Copy
【样例1】 5 【样例2】 20
题目大意:
你需要找出有多少个三元组(i,j,k)满足:
1.xi < xj < xk
2.hk > hi > hj
题目思路:
首先按照x排序之后,降维
之后,假设当前位置是pos
考虑当前位置作为第二个的贡献,即对所有之前出现过的数 大于h[pos]的+1
然后再加上pos作为第三个数的贡(即对答案的贡献)
所以你需要维护两个操作:
1.对所有出现过的数,在[x,y]区间内都+1
2.求所有出现过的数,在[x,y]区间内的权值
因为题目要求出现过,所以用线段树再次维护一个b权值,代表当前节点下,出现了多少个点
那么lazy 向下传 就不传 区间长度了 而是b[k]
每次单点修改时,将lazy传递下来,这样就不会影响新的lazy传递
Code:
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF= 1e16;
const int maxn = 1e6+7;
const int mod= 998244353;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
struct Node{
int x,y;
bool friend operator<(Node a,Node b){
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
}q[maxn];
ll sum[maxn],lazy[maxn],b[maxn];
vector<int>v;
int getid(ll x){
return lower_bound(v.begin(),v.end(),x) - v.begin() + 1;
}
void push(int k){
b[k] = b[k<<1]+b[k<<1|1];
sum[k] = sum[k<<1] + sum[k<<1|1];
}
void down(int k){
if(lazy[k]){
sum[k<<1] += lazy[k]*b[k<<1];
sum[k<<1|1] += lazy[k]*b[k<<1|1];
lazy[k<<1] += lazy[k];
lazy[k<<1|1] += lazy[k];
lazy[k] = 0;
}
}
void ModifyOne(int k,int l,int r,int pos){
if(l == r){
b[k]++;
return;
}
down(k);
int mid = (l+r)/2;
if(pos<=mid) ModifyOne(k<<1,l,mid,pos);
else ModifyOne(k<<1|1,mid+1,r,pos);
push(k);
}
void Modify(int k,int l,int r,int x,int y){
if(x<=l&&y>=r){
sum[k] += b[k];
lazy[k] ++;
return;
}
down(k);
int mid = (l+r)/2;
if(x<=mid) Modify(k<<1,l,mid,x,y);
if(y>mid) Modify(k<<1|1,mid+1,r,x,y);
push(k);
}
ll Query(int k,int l,int r,int x,int y){
if(x<=l&&y>=r) return sum[k];
down(k);
int mid = (l+r)/2;
ll ans = 0;
if(x<=mid) ans += Query(k<<1,l,mid,x,y);
if(y>mid) ans += Query(k<<1|1,mid+1,r,x,y);
push(k);
return ans;
}
int main(){
read(n);
for(int i=1;i<=n;i++){
scanf("%d%d",&q[i].x,&q[i].y);
v.push_back(q[i].y);
}
sort(q+1,q+1+n);
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
int nn = v.size();
unsigned long long ans = 0;
for(int i=1;i<=n;i++){
// printf("%d %d\n",q[i].x,q[i].y);
int k = i;
while(k<=n&&q[k].x == q[i].x){
int id = getid(q[k].y);
if(id > 2) ans += Query(1,1,nn,1,id-1);
k++;
}
k = i;
while(k<=n&&q[k].x == q[i].x){
int id = getid(q[k].y);
Modify(1,1,nn,id+1,nn);
k++;
}
k = i;
while(k<=n&&q[k].x == q[i].x){
int id = getid(q[k].y);
ModifyOne(1,1,nn,id);
k++;
}
i = k - 1;
}
printf("%llu\n",ans);
return 0;
}