1. 程式人生 > >POJ-1990 MooFest---兩個樹狀數組

POJ-1990 MooFest---兩個樹狀數組

return per #define struct pac HR 還需要 amp include

題目鏈接:

https://vjudge.net/problem/POJ-1990

題目大意:

一群牛參加完牛的節日後都有了不同程度的耳聾,第i頭牛聽見別人的講話,別人的音量必須大於v[i],當兩頭牛i,j交流的時候,交流的最小聲音為max{v[i],v[j]}*他們之間的距離。現在有n頭牛,求他們之間兩兩交流最少要的音量和。

解題思路:

使用樹狀數組,首先將二元組按照v的大小從小到大排序,這樣可以保證每頭牛比前面的牛的v大,計算它和它前面牛的音量和的時候,就可以直接用該頭牛的v,還需要計算出|a[i].x - x|絕對值之和。

用樹狀數組維護坐標x,可以直接求出比這頭牛小的所有x之和,還需要用另一個樹狀數組維護每個元素出現的次數,直接求出小於這頭牛的x的牛的數目。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #include<set>
 7 #include<cmath>
 8 #include<algorithm>
 9 #include<vector>
10 #include<sstream>
11 #define lowbot(i) (i&(-i))
12 using
namespace std; 13 typedef long long ll; 14 const int maxn = 1e5 + 10; 15 struct cow 16 { 17 ll v, x; 18 bool operator <(const cow& a)const 19 { 20 return v < a.v || v == a.v && x < a.x; 21 } 22 }a[maxn]; 23 int tree[maxn], id_num[maxn]; 24 void add(int x, int
d, int tree[]) 25 { 26 while(x <= maxn)//上限是maxn 27 { 28 tree[x] += d; 29 x += lowbot(x); 30 } 31 } 32 ll sum(int x, int tree[]) 33 { 34 ll ans = 0; 35 while(x) 36 { 37 ans += tree[x]; 38 x -= lowbot(x); 39 } 40 return ans; 41 } 42 int main() 43 { 44 int n; 45 scanf("%d", &n); 46 for(int i = 0; i < n; i++)scanf("%lld%lld", &a[i].v, &a[i].x); 47 sort(a, a + n); 48 ll num, tot, ans = 0; 49 for(ll i = 0; i < n; i++) 50 { 51 num = sum(a[i].x, id_num); 52 tot = sum(a[i].x, tree); 53 ans += (num * a[i].x - tot) * a[i].v; 54 //cout<<num<<" - "<<tot<<" + "<<ans<<endl; 55 num = i - num; 56 tot = sum(20000, tree) - tot; 57 ans += (tot - num * a[i].x) * a[i].v; 58 //cout<<num<<" - "<<tot<<" - "<<ans<<endl; 59 add(a[i].x, a[i].x, tree); 60 add(a[i].x, 1, id_num); 61 } 62 cout<<ans<<endl; 63 return 0; 64 }

POJ-1990 MooFest---兩個樹狀數組