题链:
http://poj.org/problem?id=1990
题解:
树状数组
把牛们按x坐标从小到大排序,依次考虑每头牛对左边和对右边的贡献。
对左边的贡献:从左向右枚举牛,计算以当前牛的声音为最大时和左边其它牛的贡献。
对右边的同理。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 20050 #define abs(x) (x<0?-x:x) using namespace std; struct Pii{ int a,b; Pii(int _a=0,int _b=0):a(_a),b(_b){} bool operator < (const Pii &rtm)const{return b<rtm.b;} void operator += (const Pii &rtm){a+=rtm.a; b+=rtm.b;}; }cow[MAXN]; struct BIT{ int N; Pii A[MAXN]; int Lowbit(int x){return x&-x;} void Reset(int n){N=n; memset(A,0,sizeof(A));} void Modify(int p,Pii w){ while(p<=N) A[p]+=w,p+=Lowbit(p); } Pii Query(int p){ static Pii ret; ret.a=ret.b=0; while(p) ret+=A[p],p-=Lowbit(p); return ret; } }DT; int main(){ int n; scanf("%d",&n); Pii tmp; long long ans=0; for(int i=1;i<=n;i++) scanf("%d%d",&cow[i].a,&cow[i].b); sort(cow+1,cow+n+1); for(int k=0;k<=1;k++){ DT.Reset(20000); if(k==1) reverse(cow+1,cow+n+1); for(int i=1;i<=n;i++){ tmp=DT.Query(cow[i].a-k); ans+=1ll*abs((tmp.b*cow[i].b-tmp.a))*cow[i].a; DT.Modify(cow[i].a,Pii(cow[i].b,1)); } } printf("%lld\n",ans); return 0; }