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
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 }