POJ

题目链接

题意:

给定 $N$ 头牛的位置$(x)$和听力阈值$(v)$,每两头牛之间交流需要的声音是 $max( v1, v2) * | x1 - x2 |$ ,现在要求所有牛之间交流的声音总值。

思路:

对于每两头牛之间,总是取最大的$V$ , 我们就可以按照$V$的大小排序;

那么我们就可以用当前牛的 $V *$ 已经存在的牛到当前牛的距离总和 ,并更新答案。

这里要用树状数组记录一下  下标之和 $and$ 个数 ,于是我们就两个树状数组。

 1 /*
 2 * @Author: windystreet
 3 * @Date:   2018-08-07 15:13:40
 4 * @Last Modified by:   windystreet
 5 * @Last Modified time: 2018-08-07 15:52:16
 6 */
 7 #include<stdio.h>
 8 #include<string.h>
 9 #include<algorithm>
10 
11 using namespace std;
12 
13 #define X first
14 #define Y second
15 #define eps  1e-5
16 #define gcd __gcd
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define lowbit(x) (x)&(-x)
20 #define bug printf("!!!!!
");
21 #define mem(x,y) memset(x,y,sizeof(x))
22 
23 typedef long long LL;
24 typedef long double LD;
25 typedef pair<int,int> pii;
26 typedef unsigned long long uLL;
27 
28 const int maxn = 2e4+7;
29 const int INF  = 1<<30;
30 const int mod  = 1e9+7;
31 
32 struct node
33 {
34     int x,v;
35 }s[maxn];
36 
37 LL tree[maxn][3];     // 0 下标和
38 int n;                // 1  个数
39 
40 bool cmp(node a,node b){
41     return a.v<b.v||(a.v==b.v&&a.x<b.x);
42 }
43 
44 
45 void add(int x,int v,int flag){
46     for(int i=x;i<maxn;i+= lowbit(i)){
47         tree[i][flag] += v;
48     }
49     return ;
50 }
51 LL query(int x,int flag){
52     LL res = 0;
53     for(int i=x;i;i-=lowbit(i)){
54         res += tree[i][flag];
55     }
56     return res;
57 }
58 
59 
60 void solve(){
61     scanf("%d",&n);
62     for(int i=1;i<=n;i++){
63         scanf("%d%d",&s[i].v,&s[i].x);
64     }
65     sort(s+1,s+1+n,cmp);
66     LL ans = 0,a1,a2,b1,b2;
67     for(int i=1;i<=n;i++){
68         a1 = query(s[i].x,0);         // s[i].x之前的牛的下标和
69         a2 = query(maxn-1,0) - a1;    // 所有的牛的下标和
70         b1 = query(s[i].x,1);         // s[i].x之前的牛的数量
71         b2 = query(maxn-1,1) - b1;    // 所有牛的数量
72         ans += (b1*s[i].x - a1 + a2 - s[i].x * b2) * s[i].v;  
73         add(s[i].x,s[i].x,0);         // b1 * s[i].x - a1 表示s[i].x 之前的牛到s[i].x 的距离之和
74         add(s[i].x,1,1);              // a2 - s[i].x * b2 表示s[i].x 之后的牛到s[i].x 的距离之和
75 
76     }
77     printf("%lld
",ans);
78 
79     return;
80 }
81 
82 int main()
83 {
84 //    freopen("in.txt","r",stdin);
85 //    freopen("out.txt","w",stdout);
86 //    ios::sync_with_stdio(false);
87     int t = 1;
88     //scanf("%d",&t);
89     while(t--){
90     //    printf("Case %d: ",cas++);
91         solve();
92     }
93     return 0;
94 }
原文地址:https://www.cnblogs.com/windystreet/p/9437853.html