MooFest POJ - 1990
题意:n 头牛,每两头牛之间产生的价值是 max(a[i].v , a[j].v ) * |a[i].x - a[j].x|,问产生的总费用是多少
题解:先将每头牛按照 v 的大小从小到大排序,那么就可以去掉一个绝对值并且只用当前的v的值去乘,之后用两个树状数组维护,一个树状数组维护比a[i].x小的牛有几头,另一个维护比a[i].x小的 x 的总和,之后 a[i].v * (sum1(a[i].x) * a[i].x - sum2(a[i].x)) 就是比它 x 小的费用总和,a[i].v * ((sum2[20000] - sum2(a[i].x)) - sum1(20000) - sum1(a[i].x)) * a[i].x) 就是后面的总费用
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<list> #include<math.h> #include<vector> #include<stack> #include<string> #include<cstring> #include<string.h> using namespace std; typedef long long LL; #define ll LL #define bug printf("*********\n") #define debug(x) cout<<#x"=["<<x<<"]" <<endl const int MAXN = 2e4 + 10; const double eps = 1e-8; const LL mod = 1000000007; LL sum1[MAXN],sum2[MAXN]; struct node { int x,v; }a[MAXN]; int lowbit(int x) { return x & -x; } void update1(int x,int y) { for(int i = x; i <= MAXN; i += lowbit(i)) sum1[i] += y; } void update2(int x,int y) { for(int i = x; i <= MAXN; i += lowbit(i)) sum2[i] += y; } LL getsum1(int x) { LL ans = 0; for(int i = x; i; i -= lowbit(i)) ans += sum1[i]; return ans; } LL getsum2(int x) { LL ans = 0; for(int i = x; i; i -= lowbit(i)) ans += sum2[i]; return ans; } void init() { memset(sum1,0,sizeof sum1); memset(sum2,0,sizeof sum2); } bool cmp(node x,node y) { return x.v < y.v; } int main() { init(); int n; int M = 2e4; scanf("%d",&n); for(int i = 1; i <= n; i++) scanf("%d %d",&a[i].v, &a[i].x); sort(a + 1, a + 1 + n,cmp); LL ans = 0; for(int i = 1; i <= n; i++) { // debug(getsum1(a[i].x)); // debug(getsum2(a[i].x)); // debug(getsum1(M) - getsum1(a[i].x)); // debug(getsum2(M) - getsum2(a[i].x)); ans += a[i].v * (getsum1(a[i].x) * a[i].x - getsum2(a[i].x)); // debug(ans); ans += a[i].v * ((getsum2(M) - getsum2(a[i].x)) - (getsum1(M) - getsum1(a[i].x)) * a[i].x); update1(a[i].x,1); update2(a[i].x,a[i].x); // debug(ans); } printf("%lld\n",ans); }