POJ 1990 MooFest(樹狀數組)

超級傳送門:http://poj.org/problem?id=1990


題意:X軸上有N頭牛(1<=N<=20000),每頭牛有一個聽力值v[i]和唯一的橫座標x[i]。兩頭牛直接互相通話的花費定義爲max(v[i],v[j])*abs(x[i]-x[j]),現在要求輸出所有牛互相通話的總花費。

分析:用兩個樹狀數組,一個用來存放當前位置左側牛的個數,另一個存放左側牛的橫座標。利用排序可以巧妙地避開max(v[i],v[j])的計算,先按照v從小到大對牛排序然後再依次插入樹狀數組,不影響結果。這樣的話每次計算左側的時候,乘以的v都是當前牛的v(當前最大)。

在紙上畫個圖就能看出其關係:

左側牛到當前牛距離和 = 左側牛數量 * X  -  左側牛座標和
右側牛到當前牛距離和 = 右側牛座標和 - 右側牛數量 * X


代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 20010;
struct node {
    int x,v;
}cow[maxn];
int c1[maxn]; //樹狀數組1:記錄牛的個數
int c2[maxn]; //樹狀數組2:記錄牛的x座標
int n;
int cmp(const struct node& a,const struct node& b) {
    if (a.v!=b.v) return a.v<b.v;
    return a.x<b.x;
}
int lowbit(int t) {
    return t & -t;
}
__int64 getsum1(int end) {
    __int64 ret=0;
    for (int i=end;i>=1;i-=lowbit(i)) {
        ret += c1[i];
    }
    return ret;
}
void update1(int p,int val) {
    for (int i=p;i<maxn;i+=lowbit(i)) {
        c1[i] += val;
    }
}
__int64 getsum2(int end) {
    __int64 ret=0;
    for (int i=end;i>=1;i-=lowbit(i)) {
        ret += c2[i];
    }
    return ret;
}
void update2(int p,int val) {
    for (int i=p;i<maxn;i+=lowbit(i)) {
        c2[i] += val;
    }
}
int main () {
    #ifndef ONLINE_JUDGE
        freopen("1.txt","r",stdin);
    #endif
    int n;
    __int64 ans;
    while (scanf("%d",&n)>0) {
        memset(c1,0,sizeof(c1));
        memset(c2,0,sizeof(c2));
        ans = 0;
        for(int i=1;i<=n;i++) {
            scanf("%d%d",&cow[i].v,&cow[i].x);
        }
        sort(cow+1,cow+n+1,cmp);
        for(int i=1;i<=n;i++) {
            update1(cow[i].x,1);
            update2(cow[i].x,cow[i].x);
            ans += cow[i].v*(  getsum1(cow[i].x-1)*cow[i].x //左側牛數量 * X
                              -  getsum2(cow[i].x-1) //左側牛座標和
                             +  getsum2(maxn-1) - getsum2(cow[i].x) //右側牛座標和
                             - ( getsum1(maxn-1)-getsum1(cow[i].x) )*cow[i].x ); //右側牛數量 * X
                             /*
                                左側牛到當前牛距離和 = 左側牛數量 * X  -  左側牛座標和
                                右側牛到當前牛距離和 = 右側牛座標和 - 右側牛數量 * X
                             */
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章