poj 1990 树状数组

传送门:https://vjudge.net/problem/POJ-1990

题意:m头牛,每头牛有两个值v和x。然后每两头牛之间的值是abs(x1-x2) * Max(v1,v2)。问所有m*(m-1)/2对牛之间值的总和。

白书上来的。就是用树状数组做。首先肯定是按照v排序,这样就可以不用管v了。接下来我们看看x。

我们先对所有牛的x排序,然后每头牛有一个idx代表这头牛的x在所有牛的x中排第几位。然后有两个树状数组,num[N]和dis[N]。num[i]表示比i小的有多少个,dis[i]表示比i小的x的和(这里的i指在X[N]数组排名第i位)。然后我按照v从小到大的顺序枚举每一头牛,每次进行维护,这样枚举到的牛所查询树状数组里的都是v比它小的。这样这头牛对答案的贡献就是由两部分构成。

第一部分x比它小的 就是比v×(x-xi)的和,整理就是v×(cnt×x-dis[i]),

然后我在记录目前为止总共加了多少个点进树状数组,以及这些点的x的总和totdis。

这样第二部分就是x比它大的就很好求了。

讲的可能不是很清楚,具体看代码吧。

 1 // Cease to struggle and you cease to live
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <vector>
 9 #include <set>
10 #include <map>
11 #include <stack>
12 using namespace std;
13 typedef long long ll;
14 const int N=2e4+9;
15 int n;
16 ll num[N<<2],dis[N<<2],X[N];
17 void add(int x){
18     ll val=X[x];
19     for(;x<=n;x+=x&-x) dis[x]+=val,++num[x];
20 }
21 ll qnum(int x){
22     ll ans=0;
23     for(;x>0;x-=x&-x) ans+=num[x];
24     return ans;
25 }
26 ll qdis(int x){
27     ll ans=0;
28     for(;x>0;x-=x&-x) ans+=dis[x];
29     return ans;
30 }
31 struct cow{
32     ll v,x;
33     int idx;
34     bool operator<(const cow& b) const{
35         return v<b.v;
36     }
37 }a[N];
38 int main() {
39     scanf("%d",&n);
40     for(int i=1;i<=n;++i){
41         scanf("%lld%lld",&a[i].v,&a[i].x);
42         X[i]=a[i].x;
43     }
44     sort(X+1,X+1+n);
45     sort(a+1,a+1+n);
46     for(int i=1;i<=n;++i){
47         a[i].idx=lower_bound(X+1,X+1+n,a[i].x)-X;
48     }
49     ll totcnt=0,totdis=0;
50     ll res=0;
51     for(int i=1;i<=n;++i){
52         ll lcnt=qnum(a[i].idx);
53         ll ldis=qdis(a[i].idx);
54         res+=a[i].v*(lcnt*a[i].x-ldis);
55         res+=a[i].v*((totdis-ldis)-(totcnt-lcnt)*a[i].x);
56         ++totcnt;
57         totdis+=a[i].x;
58         add(a[i].idx);
59     }
60     printf("%lld",res);
61     return 0;
62 }

原文地址:https://www.cnblogs.com/xiaobuxie/p/10859430.html

时间: 2024-10-15 19:02:26

poj 1990 树状数组的相关文章

MooFest POJ - 1990 (树状数组)

Every year, Farmer John's N (1 <= N <= 20,000) cows attend "MooFest",a social gathering of cows from around the world. MooFest involves a variety of events including haybale stacking, fence jumping, pin the tail on the farmer, and of cours

poj 2299 树状数组求逆序数+离散化

http://poj.org/problem?id=2299 最初做离散化的时候没太确定但是写完发现对的---因为后缀数组学的时候,,这种思维习惯了吧 1.初始化as[i]=i:对as数组按照num[]的大小间接排序 2.bs[as[i]]=i:现在bs数组就是num[]数组的离散化后的结果 3.注意,树状数组中lowbit(i)  i是不可以为0的,0&(-0)=0,死循环... #include <cstdio> #include <cstring> #include

POJ 2352Stars 树状数组

Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42898   Accepted: 18664 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a st

SYSU-5, POJ 2131, 树状数组+二分

题目大意:给出n个人,顺序对位置进行请求,如果第i个人请求的位置上有人,则让这个人顺延,如果顺延的位置继续有人,递归进行,问最后所有人的位置. 解:这题貌似可以用平衡树+并查集搞定,但是我队友强烈安利树状数组的做法.赛场上没出,赛后结合discuz想了一下,作一下处理. 首先如果是一个请求第a[i]个有空位置的问题,那么这个问题显然可以用树状数组维护前缀和即可.所以我们现在考虑将原问题转化成这个问题. 考虑终态,把没有人的位置去掉,剩下的n个座位排在一起,显然转化成上面模型的形式 第i个询问时,

POJ 1201 树状数组

链接: http://poj.org/problem?id=1201 题意: 给你n个区间,每个区间为[a,b],每个区间取c个数构成一个集合,求集合最小容量 题解: 把区间按b排序,从第一个区间开始取,从后往前取,这样尽可能和后面的区间重复 另外如果我们发现当前区间取得个数已经超过了c,那么只需要让之前区间换就行,而总数是不变的,所以不用更新答案 求当前区间已经取了多少个数用树状数组 代码: 1 #include <map> 2 #include <set> 3 #include

POJ 3321 树状数组(+dfs+重新建树)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27092   Accepted: 8033 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

poj 2182 树状数组

倒着考虑,如果最后一只牛的前面有x只比它小,那么它就是第x+1只牛,从序列中去掉它.对倒数第二只牛来说也同理.可以用树状数组来维护前缀和,一开始每个位置都是1,求出结果的牛从树状数组中删掉(update成0),即可获得答案. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 8001; 7 int c[N]; 8

poj 2352 树状数组

Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the given star. As

poj 3928 树状数组

题目中只n个人,每个人有一个ID和一个技能值,一场比赛需要两个选手和一个裁判,只有当裁判的ID和技能值都在两个选手之间的时候才能进行一场比赛,现在问一共能组织多少场比赛. 由于排完序之后,先插入的一定是小的,所以左右两边的大于小于都能确定,用树状数组维护选手的id Sample Input13 1 2 3Sample Output1 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #incl