zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    51 }
  • 相关阅读:
    3.15第三周编程总结
    2019.3.9编程总结
    2019.3.3编程总结2
    编程总结1
    编程总结2
    编程总结3
    我的老师
    关于sublime text 3使用记录
    12. 整数转罗马数字
    4. 寻找两个有序数组的中位数
  • 原文地址:https://www.cnblogs.com/refun/p/10518298.html
Copyright © 2011-2022 走看看