BZOJ3378:[USACO]MooFest 狂欢节(树状数组)

Description

每一年,约翰的N(1≤N≤20000)只奶牛参加奶牛狂欢节.这是一个全世界奶牛都参加的大联欢.狂欢节包括很多有趣的活动,比如干草堆叠大赛、跳牛栏大赛,奶牛之间有时还相互扎屁股取乐.当然,她们会排成一列嚎叫,来欢庆她们的节日.奶牛们的叫声实在刺耳,以致于每只奶牛的听力都受到不同程序的损伤.现在告诉你奶牛i的听力为vi(l≤Vi≤20000),这表示如果奶牛j想说点什么让她听到,必须用高于vi×dis(i,j)的音量.而且,如果奶牛i和j想相互交谈,她们的音量必须不小于max(Vi,Vj)×dis(i,j).其中dis(i,J)表示她们间的距离.
现在N只奶牛都站在一条直线上了,每只奶牛还有一个坐标xi(l≤xi≤20000).如果每对奶牛都在交谈,并且使用最小音量,那所有n(n-1)/2对奶牛间谈话的音量之和为多少?

Input

第1行输入N,之后N行输入Vi和xi.

Output

输出音量之和.

Sample Input

4
3 1
2 5
2 6
4 3

Sample Output

57

Solution

首先把奶牛按听力排序,那么$max(vi,vj)~(j<i)$一定是$v_i$。问题变成了对于每个$i$,求它和前面奶牛的$dis$和。

开两个树状数组$A$和$B$,$A_i$表示下标为$i$的奶牛的坐标和,$B_i$表示下标为$i$的奶牛的个数,然后算一下就好了。

Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define N (20009)
 5 #define LL long long
 6 using namespace std;
 7 
 8 int n;
 9 pair<int,int>a[N];
10 LL ans,p1,q1,p2,q2;
11 
12 struct BIT
13 {
14     LL c[N];
15     
16     void Update(int x,int k)
17     {
18         for (; x<=20000; x+=(x&-x)) c[x]+=k;
19     }
20     LL Query(int x)
21     {
22         LL ans=0;
23         for (; x; x-=(x&-x)) ans+=c[x];
24         return ans;
25     }
26 }A,B;
27 
28 inline int read()
29 {
30     int x=0,w=1; char c=getchar();
31     while (c<'0' || c>'9') {if (c==-'-') w=-1; c=getchar();}
32     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
33     return x*w;
34 }
35 
36 int main()
37 {
38     n=read();
39     for (int i=1; i<=n; ++i) a[i].first=read(), a[i].second=read();
40     sort(a+1,a+n+1);
41     for (int i=1; i<=n; ++i)
42     {
43         int v=a[i].first,x=a[i].second;
44         A.Update(x,x); B.Update(x,1);
45         LL p1=A.Query(x-1),q1=B.Query(x-1);
46         ans+=v*(q1*x-p1);
47         LL p2=A.Query(20000)-A.Query(x),q2=B.Query(20000)-B.Query(x);
48         ans+=v*(p2-q2*x);
49     }
50     printf("%lld\n",ans);
51 }

猜你喜欢

转载自www.cnblogs.com/refun/p/10518298.html