这里是题目链接:题目链接
因为高度只要求取两点中最小的那个所以我们先按高度从小到大排序,那么每次枚举的hi肯定就是最小的啦,然后用树状数组维护区间和和区间数就可以了。
题解:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int mx=100010;
int n,m,a1[mx],cnt[mx];
struct data{
int coor,hi;
bool operator < (data A)const{
if(hi==A.hi) return coor<A.coor;
return hi<A.hi;
}
}s[mx];
ll sum[mx][2];//第一个数量,第二个是总和
inline int lowbit(int x){
return x&(-x);
}
void add(int x,int va){
for(int i=x;i<=n;i+=lowbit(i)){
sum[i][0]+=va;
sum[i][1]+=va*x;
}
}
ll sums(int x,int va){
ll ans= !va? cnt[x]:x*cnt[x];
x--;
while(x>0){
ans+=sum[x][va];
x-=lowbit(x);
}
return ans;
}
int main(){
int cases=1;
s[0].coor=s[0].hi=0;
while(cin>>n){
for(int i=1;i<=n;i++){
scanf("%d%d",&s[i].coor,&s[i].hi);
a1[i]=s[i].coor;
}
sort(a1+1,a1+1+n);
sort(s+1,s+1+n);
int num[2]={0,0},id=0;
for(int i=1;i<=n;i++,id^=1){
num[id^1]=s[i].hi;
s[i].coor=lower_bound(a1+1,a1+n+1,s[i].coor)-a1;
if(s[i].hi!=num[id]) s[i].hi=i;
else s[i].hi=s[i-1].hi;
cnt[s[i].coor]++;
add(s[i].coor,1);
}
ll ans=0;
for(int i=1;i<=n;i++){
int val=s[i].coor;
ans+=s[i].hi*(2*val*sums(val-1,0)-2*sums(val-1,1)+sums(n,1)-val*sums(n,0));
//小于val的数可以直接去绝对值,大于的加个负号,分为这两部分
cnt[val]--;
add(val,-1);
}
printf("%lld\n",ans);
}
return 0;
}