对于树状数组的理解不透+不会转化
题解:显然是要按照v排序的,那么首先在On情况下是可以完成max(vi,vj)的操作,对于某个牛i,我们只需考虑i之前的,那么i之前的牛我们需要知道每只牛j ,abs(dis(i) - dis(j)),去掉绝对值后,我们只需要知道所有dis(j) < dis(i)的牛的x的和 sum1,dis(j) > dis(i)的我们可以用总距离 - sum1 ,以及知道< dis(i) 的牛的个数num1,那么我们变可以用2个树状数组来分别维护了,
于是ans += ((num1 * x - sum1) + ( sum2 - sum1 - (i - num1) * x)))*v;
很巧妙啊
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define fuck() (cout << " ------------------ " << endl)
const double eps = 1e-6;
const int maxn = 20000 + 5;
using namespace std;
struct node{
int x,v;
node(){}
node(int x_, int v_):x(x_),v(v_){}
bool operator < (const node & p) const {
if(v == p.v)
return x < p.x;
return v < p.v;
}
}cow[maxn];
LL sum[maxn];
LL num[maxn];
int lowbit(int x){
return x & (-x);
}
void add(int x, int c, LL a[]){
while(x <= maxn){
a[x] += c;
x += lowbit(x);
}
}
LL getsum(int x, LL a[]){
LL ans = 0;
while(x){
ans += a[x];
x -= lowbit(x);
}
return ans;
}
int main(){
int n;
while(scanf("%d",&n) == 1){
for(int i=0; i<n; i++)
scanf("%d%d",&cow[i].v,&cow[i].x);
sort(cow, cow+n);
memset(sum, 0, sizeof(sum));
memset(num, 0, sizeof(num));
LL ans = 0;
for(int i=0; i<n; i++){
int x = cow[i].x;
int v = cow[i].v;
LL num1 = getsum(x,num);
LL sum1 = getsum(x,sum);
LL sum2 = getsum(maxn,sum);
ans += (num1 * x - sum1 + sum2 - sum1 - (i - num1) * x)*v;
add(x,1,num);
add(x,x,sum);
}
printf("%lld\n",ans);
}
}