题意:
- 牛i和j沟通,音量为abs(c[i].x-c[j].x) * max(c[i].v,c[j].v);
- 求任意两头牛通话的音量总和
题解
- 按牛的耳背程度从小到大排序
- 每加入一头牛,其耳背程度一定是最大的。然后,算出与之前牛的距离之和
- 维护距离≤xi的坐标之和sum,和数量num,则ans += (num * c[i].x - sum) * c[i].v
- 同理可以算出距离>xi的。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
int const N = 20000 + 10;
ll n;
ll sum[N],num[N],ans;
struct Cow
{
int v,x;
bool operator < (const Cow& e) const{
return v < e.v;
}
}c[N];
ll lowbit(ll x){return x&-x;}
void add(ll c[N],ll i,ll x){
while(i <= N){
c[i] += x;
i += lowbit(i);
}
}
ll getsum(ll c[N],ll i){
ll sum = 0;
while(i){
sum += c[i];
i -= lowbit(i);
}
return sum;
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&c[i].v,&c[i].x);
sort(c+1,c+1+n);
ll tot = 0;
for(int i=1;i<=n;i++){
int low = getsum(num,c[i].x-1); //比c[i].x小的数的个数
ll s = getsum(sum,c[i].x-1); //比c[i].x小的距之和
ans += c[i].v * (low * c[i].x - s);
ans += c[i].v * ((tot - s) - c[i].x * (i - low - 1)); //比c[i].x大牛
add(sum,c[i].x,c[i].x);
add(num,c[i].x,1);
tot += c[i].x;
}
printf("%lld\n",ans);
return 0;
}