码迷,mamicode.com
首页 > 编程语言 > 详细

MooFest(POJ-1990)(树状数组)

时间:2015-05-02 20:47:20      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:acm   poj   

最近学习了一下树状数组,这道题纠结了很久,终究是因为没有明白树状数组怎么用。

感觉网上许多大神都只是讲原理,对于我们这些初学的菜鸟恐怕都被吓跑了。

这里我就以实用主义说一下使用方法(其实我觉得其原理应该能对我们更有启发,也许会带来很多潜在的好处):

这里需要注意的是,bit的实现代码中的bit数组一开始必须清零,这个数组并不是用来储存元素的,而是为实现这个数据结构而存在的。  你需要存储的元素是要通过那个add函数添加的,而求和则是要通过sum函数实现的,而这个bit数组的结构并不是对于一个新手很容易理解的,我们也大可不必关心这个。

另外要注意一个地方,在add函数里那个n,要开的足够大,不然你是添加不进去的,比如你要是把n=10,求sum(100) 会得到0 。

举个例子: 输入n个元素,求前n个元素的和。代码如下

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int bit[1000],n;
int sum(int i) {
    int s = 0;
    while(i>0) {
        s+=bit[i];
        i-=i& -i;
    }
    return s;
}
int add(int i,int x){
    while(i <= n){
        bit[i] += x;
        i += (i & -i);
    }
}
int main() {
    while(~scanf("%d",&n)) {
        memset(bit,0,sizeof(bit));
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            add(i,x);
        }
        for(int i=1;i<=n;i++) printf("%d\n",sum(i));
    }
    return 0;
}

相信看了上面的代码就可以很清晰的明白了,第几个元素,是要输入进add函数的,你输入的i是几,那么这个元素就是树状数组中的第几个元素。与bit数组无关,这个数组只是为了实现特定的数据结构而存在的辅助函数罢了。

该题代码是参考了别人的。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int max_n = 20000+4;
ll cnt_bit[20005]={0},distance_bit[20005]={0};
int n;
struct point {
    int  v,x;
}a[20005];
bool cmp(point a,point b) {
    return a.v<b.v;
}
ll  sum_(ll *bit,int i) {
    ll s = 0;
    while(i>0) {
        s+=bit[i];
        i-=i & -i;
    }
    return s;
}
ll sum(ll *a,int i,int j) {
    return sum_(a,j-1) - sum_(a,i-1);
}
void add(ll *bit,int i,int x) {
    while(i<=max_n) {
        bit[i] += x;
        i += i&-i;
    }
}
int main() {
    ll tot = 0;
    scanf("%d",&n);
    memset(cnt_bit,0,sizeof(cnt_bit));
    memset(distance_bit,0,sizeof(distance_bit));
    for(int i=0;i<n;i++) scanf("%d%d",&a[i].v,&a[i].x);
    sort(a,a+n,cmp);
    for(int i=0;i<n;i++) {
        int v = a[i].v;
        int  x = a[i].x;
        ll  left = sum(cnt_bit,1,x) ;
        ll  right = sum(cnt_bit,x+1,max_n);
        tot+=((left*x-sum(distance_bit,1,x)) + (sum(distance_bit,x+1,max_n)-right*x))*v;
        add(cnt_bit,a[i].x,1);
        add(distance_bit,a[i].x,a[i].x);
    }
    printf("%lld\n",tot);
    return 0;
}



MooFest(POJ-1990)(树状数组)

标签:acm   poj   

原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/45441605

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!