有一天,索菲亚(Sophia)找到了一个很大的广场。广场上有n棵树。他们都很高。索菲娅对他们非常有趣。
她发现树可能不和谐,并且两棵树之间的不和谐值与两个值FAR和SHORT相关联。
FAR的定义如下:如果我们将所有这些树按照它们的X坐标按升序排列,则X坐标最小的树排名第一,X坐标相同的树排名相同。例如,如果有5棵树,它们的X坐标为3、3、1、3、4。那么他们的等级可能是2、2、1、2、5。X坐标为D1和D2的两棵树的FAR定义为F = abs(D1-D2)。
SHORT的定义类似于FAR。如果将所有这些树按照它们的高度升序排列,则高度最短的树排名第一。相同高度的树排名相同。例如,如果有5棵树的高度分别为4,1,9,7,4。那么他们的等级可能是2、1、5、4、2。高度等级为H1和H2的两棵树的SHORT定义为S = min(H1,H2)。
两棵树的不和谐值定义为F * S。因此,从上面的定义可以看出,如果两棵树的FAR较大,则不和谐值较大。Disharmony值也与两棵树中较短的一棵树相关。
现在为您提供每棵树的X坐标及其高度,请告诉Sophia所有树中每两棵树的Disharmony值的总和。
输入项
输入中有几个测试用例
对于每个测试用例,第一行包含一个整数N(2 <= N <= 100,000)N表示树的数量。
然后在N行之后,每行包含两个整数:X,H(0 <X,H <= 1,000,000,000),指示树位于坐标X中并且其高度为H.
对于每个测试用例,第一行包含一个整数N(2 <= N <= 100,000)N表示树的数量。
然后在N行之后,每行包含两个整数:X,H(0 <X,H <= 1,000,000,000),指示树位于坐标X中并且其高度为H.
输出量
对于每个测试用例,输出所有树中每两棵树的Disharmony值的总和。答案在带符号的64位整数内。
样本输入
2
10 100
20 200
4
10 100
50 500
20 200
20 100
样本输出
1
13
思路: 先按照题目意思排序得到数据的两个等级
因为求的是每两个树的F*S 所以 对h的等级 进行升序排序之后 保证的是当前的hh 就是最小的 h= min(h1,h2)
定义两个树状数组 c用来处理一个数前面或者后面比它大或者小的数之和,d用来处理这个数前面或者后面有多少个数
循环计算答案
当前第i个的 F*S=(xiao-da)*a[i].hh
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+5; struct node{ int x,h,xx,hh; }a[maxn]; bool cmp1(node u,node v){ return u.x<v.x; } bool cmp2(node u,node v){ return u.h<v.h; } bool cmphh(node u,node v){ return u.hh<v.hh; } long long c[maxn],d[maxn],n; //c用来处理一个数前面或者后面比它大或者小的数之和,d用来处理这个数前面或者后面有多少个数 int lowbit(int x) { return x&(-x); } void updatac(int i,int j) { while(i<=n) { c[i]+=j; i+=lowbit(i); } } void updatad(int i,int j) { while(i<=n) { d[i]+=j; i+=lowbit(i); } } long long getsumc(int x) { long long s=0; while(x>0) { s+=c[x]; x-=lowbit(x); } return s; } long long getsumd(int x) { long long s=0; while(x>0) { s+=d[x]; x-=lowbit(x); } return s; } int main(){ while(~scanf("%d",&n)){ for(int i=1;i<=n;i++){ scanf("%d %d",&a[i].x,&a[i].h); } sort(a+1,a+n+1,cmp1); a[1].xx=1; for(int i=2;i<=n;i++){ if( a[i].x==a[i-1].x ) a[i].xx=a[i-1].xx; else a[i].xx=i; } int max=a[n].xx; sort(a+1,a+n+1,cmp2); a[1].hh=1; for(int i=2;i<=n;i++){ if( a[i].h==a[i-1].h ) a[i].hh=a[i-1].hh; else a[i].hh=i; } sort(a+1,a+1+n,cmphh); // for(int i=1;i<=n;i++){ // cout<<a[i].x<<" "<<a[i].xx<<" "<<a[i].h<<" "<<a[i].hh<<endl; // } for(int i=1;i<=n;i++) { updatac(a[i].xx,a[i].xx); updatad(a[i].xx,1); } long long sum=0,xiao,da; for(int i=1;i<=n;i++) { xiao=getsumd(a[i].xx-1)*a[i].xx-getsumc(a[i].xx-1); //找出比这个数小的个数*这个数-比这个数小的所有数之和 da=(getsumd(max)-getsumd(a[i].xx))*a[i].xx-(getsumc(max)-getsumc(a[i].xx)); //找出比这个数大的数的和-这个数 * 比这个数大的个数 sum+=(xiao-da)*a[i].hh; updatac(a[i].xx,-a[i].xx); //把这个用过的数从删除 updatad(a[i].xx,-1);//把这个数位置上减去1 } printf("%I64d\n",sum); } return 0; }