题目:http://poj.org/problem?id=1990
思路见代码:
#include<cstdio> #include<algorithm> #include<cstdlib> #include<iostream> using namespace std; const int MAX_N=20000+5; typedef long long ll; /*cnt:= 坐标小于 x的点的个数(cnt[x]) cntsum:= 坐标小于x的坐标点总和 */ ll cnt[MAX_N],cntsum[MAX_N]; int N; struct cow{ ll v,x; }nc[MAX_N]; bool cmp(cow a,cow b){ return a.v<b.v; } void update(ll *cnt,int x,int w) { while(x<=MAX_N) { cnt[x] += w; x += x&(-x); } } ll sum(ll *cntsum,int x) { ll res=0; while(x) { res += cntsum[x]; x -= x&(-x); } return res; } int main() { while(cin>>N) { for(int i=0;i<N;i++){ cin>>nc[i].v>>nc[i].x; } sort(nc,nc+N,cmp); ll tot=0,res=0; for(int i=0;i<N;i++) { ll num1=sum(cnt,nc[i].x); ll num2=sum(cntsum,nc[i].x); /* 考虑统计第i头牛,之前统计的i-1头牛v都小于等于v[i], 这些牛的坐标小于x[i]的头数为cnt[i], 这些小于x[i]的总坐标和为cntsum[i] 那这第i头牛和之前的牛交流的总和分为两部分,一部分是坐标在x之前的, 一部分是坐标在x之后的。 (cnt[i]*x[i]-cntsum[i])*v[i]为坐标在x[i]之前的牛的总和 tot为之前i-1头牛的总的坐标和,那么tot-cntsum[i]就是 坐标在x[i]之后的所有牛的坐标和,i-num1为坐标在x[i]之后的牛的头数. */ res += nc[i].v*(num1*nc[i].x-num2+ tot-num2-(i-num1)*nc[i].x); tot += nc[i].x; update(cnt,nc[i].x,1); update(cntsum,nc[i].x,nc[i].x); } cout<<res<<endl; } return 0; }
作者:xiaozhuaixifu 发表于2013-9-19 13:24:22 原文链接
阅读:69 评论:0 查看评论