题目大意:有n头牛,第i头牛声调为v[i],坐标为x[i],任意两值牛i,j沟通所需的花费为abs(x[i]-x[j])*max(v[i],v[j]),求所有牛两两沟通的花费。
分析:
我们将奶牛按声调升序排列,然后从前往后计算,由于奶牛i前面的奶牛声调都比它小,则最大声调被确定为v[i],然后只要计算之前所有奶牛与该奶牛距离即可。
如何快速求出距离和?可以知道对于奶牛j,当它比奶牛i靠左时,其距离为(x[i]-x[j]),前面所有比i靠左的奶牛与奶牛i距离和为∑(x[i]-x[j])然而它也就是∑x[i]-∑x[j],前面一项等于x[i]*(左边奶牛个数),后一项就是左边奶牛坐标数值和,两者相减的到结果要乘v[i],右边的情况也一样,左右两边相加,就是这头牛与比它小的奶牛的花费,把每头牛的总花费加起来就是结果。
代码:


program fest; var bit:array[1..2,0..20000]of int64; v,x:array[0..20000]of int64; n,m,s,a,b,t,g,ans:int64; i:longint; procedure qsort(l,h:longint); var i,j,t,m:longint; begin i:=l; j:=h; m:=v[(i+j) div 2]; repeat while v[i]<m do inc(i); while m<v[j] do dec(j); if i<=j then begin t:=v[i]; v[i]:=v[j]; v[j]:=t;t:=x[i]; x[i]:=x[j]; x[j]:=t; inc(i); dec(j); end; until i>j; if i<h then qsort(i,h); if j>l then qsort(l,j); end; procedure add(l,i,k:longint); begin while i<=m do begin inc(bit[l,i],k); inc(i,i and (-i)); end; end; function query(l,i:longint):int64; var s:longint; begin s:=0; while i>0 do begin inc(s,bit[l,i]); dec(i,i and (-i)); end; exit(s); end; begin assign(input,'fest.in'); reset(input); assign(output,'fest.out'); rewrite(output); readln(n); for i:=1 to n do begin readln(v[i],x[i]); if x[i]>m then m:=x[i]; end; qsort(1,n); for i:=1 to n do begin a:=query(1,x[i]); b:=query(2,x[i]); s:=a*x[i]-b; t:=query(1,m)-a; g:=query(2,m)-b; inc(s,g-x[i]*t); inc(ans,v[i]*s); add(1,x[i],1); add(2,x[i],x[i]); end; writeln(ans); close(input); close(output); end.