POJ 1990 MooFest【 树状数组 】

题意:给出n头牛,每头牛有一个听力v,坐标x,两头牛之间的能量为max(v1,v2)*dist(v1,v2),求总的能量值

先将每头牛按照v排序,排完顺序之后,会发现有坐标比当前的x小的,会有坐标比当前的x大的

假设坐标比x小的有num个

那么

距离之和 = x*num - 前面坐标的和 + 后面坐标的和 - (n-num-1)* x

又因为

后面坐标的和 = 整个区间坐标的和 - 前面坐标的和

所以用两个数组,一个数组用来算个数,另外一个数组用来算和

学习的这一篇题解--http://www.acmtime.com/?p=403

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include <cmath>
 5 #include<stack>
 6 #include<vector>
 7 #include<map>
 8 #include<set>
 9 #include<queue>
10 #include<algorithm>
11 using namespace std;
12
13 typedef long long LL;
14 const int INF = (1<<30)-1;
15 const int mod=1000000007;
16 const int maxn=20005;
17
18 LL a[maxn];//这个是用来求比x小的个数的
19 LL b[maxn];//这个是用来求前面的和
20 LL c[maxn];
21 int n;
22
23 struct node{
24     int x,v;
25 }q[maxn];
26
27 int cmp(node n1,node n2){
28     return n1.v < n2.v;
29 }
30
31 int lowbit(int x){ return x & (-x);}
32
33 LL sum(LL c[],int x){
34     LL ret=0;
35     while( x >0){
36         ret += c[x]; x-=lowbit(x);
37     }
38     return ret;
39 }
40
41 void add( LL c[],int x,int d){
42     while(x < maxn){
43         c[x]+=d;x+=lowbit(x);
44     }
45 }
46
47 int main(){
48     scanf("%d",&n);
49     for(int i=1;i<=n;i++) scanf("%d %d",&q[i].v,&q[i].x);
50     sort(q+1,q+n+1,cmp);
51
52     memset(a,0,sizeof(a));
53     memset(b,0,sizeof(b));
54     LL cnt =0;
55     for(int i=1;i<=n;i++){
56         int x = sum(a,q[i].x); //统计坐标比x小的有多少个
57         LL alltotal = sum(b,maxn);//统计这个区间所有坐标的和
58         LL total = sum(b,q[i].x);//统计前面坐标比x小的的和
59         cnt += q[i].v * (x * q[i].x - total + alltotal - total - ( i - x -1) * q[i].x);
60         add(a,q[i].x,1);
61         add(b,q[i].x,q[i].x);
62     }
63     printf("%I64d\n",cnt);
64     return 0;
65 }

加油-------------

goooooooooooooo-------- -------

时间: 2024-10-31 17:48:59

POJ 1990 MooFest【 树状数组 】的相关文章

POJ 1990 MooFest 树状数组

这题是我看了大白书树状数组后刷的第一道题,确实难度不小,所以只好上网找题解了,网上的做法确实精彩.这题的题意主要是有N头牛,每两头牛之间交流的费用为它们的距离乘上两者音量的最大值(即max(v(i),v(j))),然后统计所有牛两两交流的总费用.一开始能想到的做法便是O(n2)的暴力枚举了,当时的我也只能想到这样的复杂度,很纳闷怎么能和树状数组搭上边呢?然后看了别人的题解后才惊叹其思路之妙. 在博客 http://www.cnblogs.com/Fatedayt/archive/2011/10/

POJ 2309 BST 树状数组基本操作

Description Consider an infinite full binary search tree (see the figure below), the numbers in the nodes are 1, 2, 3, .... In a subtree whose root node is X, we can get the minimum number in this subtree by repeating going down the left node until t

POJ1990 MooFest 树状数组(Binary Indexed Tree,BIT)

N头牛排成一列,每头牛的听力是Vi,每头牛的位置Pi,任意两头牛i,j相互交流时两头牛都至少需要发出声音的大小为max(Vi,Vj) * |Pi-Pj|,求这N头牛两两交流总共发出的声音大小是多少.N,V,P都是1-20000的范围. 这题首先对Vi从小到大进行排序,排序过后就可以依次计算i,将所有比Vi小的牛到i之间的距离之和乘以Vi得到Ri,然后累加Ri就是最终结果.问题是Ri具体该如何求. 假设听力比Vi小的牛并且位置也比Pi小的牛的个数为Ci,并且这些距离之和为Si,听力比Vi小的所有牛

Poj 2299 Ultra-QuickSort 树状数组 解法

本题的树状数组稍微有点特点,就是需要所谓的离散化一下,开始听这个名称好像很神秘的,不过其实很简单. 就是把一个数组arr的值,其中的值是不连续的,变成一组连续的值,因为这样他们的顺序是不变的,所以,不影响结果. 例如:9 1 0 5 4 ->变为:5 2 1 4 3看出他们的相对位置不变的. 9和5为最大值在第一个位置,1和2为第二大的值在第二个位置,0和1在第一个位置等,看出对应顺序了吗? 对,就是这么简单的方法, 就叫做离散化. 如果你对counting sort熟悉的话,那么这样的思想理解

POJ 2481 Cows(树状数组)

Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good. Farmer John has N cows (we number the cows from 1 to N). Ea

POJ 2352 Stars(树状数组 or 线段树)

链接: http://poj.org/problem?id=2352 题目大意: 在坐标上有n个星星,如果某个星星坐标为(x, y), 它的左下位置为:(x0,y0),x0<=x 且y0<=y.如果左下位置有a个星星,就表示这个星星属于level x 按照y递增,如果y相同则x递增的顺序给出n个星星,求出所有level水平的数量. 思路: 由于输入的顺序,对于第i颗星星,它的等级是之前输入的星星中,横坐标x小于等于i星横坐标的那些星星的总数量(前面的y一定比后面的y小). 所以是查询+更新操作

poj 2481 Cows 树状数组解法,详细解析。

Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13445   Accepted: 4448 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in hi

POJ 2481 Cows &amp;&amp; POJ 2352 Stars(树状数组妙用)

题目链接:POJ 2481 Cows POJ 2352 Stars 发现这两个题目都跟求逆序数有着异曲同工之妙,通过向树状数组中插入点的位置,赋值为1,或者++,然后通过求和来判断比当前 点 "小" 的有多少点. Cows需要自己排序, Stars题目已经给排好序. POJ 2352 Stars 题目大意为在二维坐标上给出一些星星的坐标,求某一个星星左方,下方,左下方的星星个数.题目已经把星星按照Y坐标从小到大,X从小到大排序.因此,在每次对一个星星进行统计时,之前出现过的星星,只要X

POJ 2299 Ultra-QuickSort(树状数组 + 离散)

链接:http://poj.org/problem?id=2299 题意:给出N个数组成的数列A(0 <= A[i] <= 999,999,999),求该数列逆序对的数量. 分析:题目所谓的排序过程其实就是一个冒泡排序的过程.在这里,我们需要知道,冒泡排序所需交换的次数等于该序列逆序对的数量(证明略).这是这道题的一个切入点. 树状数组可以很方便地求出数列的前缀和,对于一个数x,我们使树状数组上第x个元素的值赋为1,这时调用Sum(x)就可以得到一个从第1项到第x项的前缀和.这意味着我们可以通

POJ 2352 【树状数组】

题意: 给了很多星星的坐标,星星的特征值是不比他自己本身高而且不在它右边的星星数. 给定的输入数据是按照y升序排序的,y相同的情况下按照x排列,x和y都是介于0和32000之间的整数.每个坐标最多有一个星星. 思路: 这题给的输入数据很祥和,间接提示思路了. 用x作为树状数组的区间,然后按照输入的顺序不断查找在包括自己的位置以及左边的星星数. 细节是x可能是0,这是树状数组不能接受的,需要对输入的x数据进行加一操作. 从这题可以看出树状数组最直白的作用就是求从1开始到某个点的某个区间的数量. #