您的位置:首页 > Web前端

poj 1990 MooFest 树状数组

2017-10-21 17:55 351 查看
题意就是有N头牛,每头牛都有一个坐标和声调值(x, v),两头牛之间通讯要花费的能量是他们的距离乘以最大的一个音调值,现在要任意两头牛之间都相互通讯一次,求总共需要花费多少能量?

准备两个树状数组,并且正反进行两次。

分别找左边还有右边,两个数组存别存放个数和长度、

#include<iostream>  

#include<algorithm>  

#define lowbit(x) (x&(-x))  

using namespace std;  

const int MAX = 20005;  

   

struct data{  

    int x, w;  

}cow[MAX];  

int arNum[MAX], arDis[MAX];  

   

bool cmp(data a, data b){  

    return a.x < b.x;  

}  

   

void add(int i, int *ar, int w){  

    while(i <= MAX-1){  

        ar[i] += w;  

        i += lowbit(i);  

    }  

}  

   

__int64 sum(int i, int *ar){  

    __int64 ans = 0;  

    while(i > 0){  

        ans += ar[i];  

        i -= lowbit(i);  

    }  

    return ans;  

}  

   

int main(){  

    int n, i;  

    __int64 preNum, preDis;  

    scanf("%d", &n);  

    for(i = 0; i < n; i ++)  

        scanf("%d%d", &cow[i].w, &cow[i].x);  

    sort(cow, cow + n, cmp);  

    __int64 ans = 0;  

    memset(arNum, 0, sizeof(arNum));          //  求向左的总能量。  

    memset(arDis, 0, sizeof(arDis));  

    for(i = 0; i < n; i ++){  

        preNum = sum(cow[i].w-1, arNum);  

        preDis = sum(cow[i].w-1, arDis);  

        ans += (preNum * cow[i].x - preDis) * cow[i].w;  

        add(cow[i].w, arNum, 1);  

        add(cow[i].w, arDis, cow[i].x);  

    }  

    memset(arNum, 0, sizeof(arNum));          //  求向右的总能量。  

    memset(arDis, 0, sizeof(arDis));  

    for(i = n-1; i >= 0; i --){  

        preNum = sum(cow[i].w, arNum);        //  这里不要用w-1,考虑了声调相等的情况。  

        preDis = sum(cow[i].w, arDis);  

        ans += (preDis - preNum * cow[i].x) * cow[i].w;  

        add(cow[i].w, arNum, 1);  

        add(cow[i].w, arDis, cow[i].x);  

    }  

    printf("%I64d\n", ans);  

    return 0;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: