题意:有m头牛,每头牛有两个值,v和x,两两之间有一个值,设v分别为v1,v2,x为x1,x2,则它们之间的值为abs(x1-x2) * Max(v1,v2),求所有m*(m-1)/2对牛之间值的总和。
思路:咋看第一眼都是暴力这个优秀算法,不过暴力肯定是不行的,所以要树状数组优化
我们可以先将牛以V排序,这时只需要考虑每一个 i 左右的X的情况
// #include<bits/stdc++.h>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring> // for memset
#include <vector> // push_back() // vector<int>().swap(v);
#include <set> //multiset set<int,greater<int>> //big->small
#include <map>
#include <stack> // top()
#include <queue> // front() // priority_queue<T,vector<T>,greater<T> >
#include <cmath> // auto &Name : STLName Name.
#include <utility>
#include <sstream>
#include <string> // __builtin_popcount (ans); // 获取某个数二进制位1的个数
#include <cstdlib> // rand()
#define IOS ios_base::sync_with_stdio(0); cin.tie(0)
using namespace std;
typedef long long ll;
int lowbit(int x){ return x&(-x);}
const int maxn = 20010;
struct Node
{
int x,v;
bool operator< (const Node& s)const{return v<s.v;}
}node[maxn];
int n;
int treeCount[maxn];
int treeDis[maxn];
ll sum(int x,int *t)
{
ll ans=0;
while(x)
{
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
void add(int x,int v,int *t)
{
while(x<maxn)
{
t[x]+=v;
x+=lowbit(x);
}
}
ll solve()
{
ll ans=0;
ll totalDis=0;
memset(treeCount , 0 , sizeof(treeCount));
memset(treeDis , 0 , sizeof(treeDis));
sort(node,node+n);
for(int i=0;i<n;i++)
{
ll count=sum(node[i].x,treeCount);
ll dis=sum(node[i].x,treeDis);
ans+=node[i].v*(count*node[i].x-dis);
ans+=node[i].v*((totalDis-dis-(i-count)*node[i].x));
totalDis += node[i].x;
add(node[i].x , 1 , treeCount);
add(node[i].x , node[i].x , treeDis);
}
return ans;
}
int main(void)
{
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d%d",&node[i].v,&node[i].x);
printf("%lld
",solve());
}
return 0;
}