MooFest
Description
题意翻译:
John有N头奶牛 (1 <= N <= 20,000),它们定期举行以一种叫MooFestde的活动,其实就是互相乱喊。
所有奶牛站成一条线,第i头奶牛坐标为x[i],每头奶牛有一个听力值v[i].
如果两头奶牛要对话,至少要发出大小为 abs(x[i]-x[j])*max(v[i], v[j] )的声音。
现在每两头奶牛都在对话( 有 n*(n+1)/2 个声音),求这些声音大小的和。
Input
* Line 1: A single integer, N
* Lines 2..N+1: Two integers: the volume threshold and x coordinate for a cow. Line 2 represents the first cow; line 3 represents the second cow; and so on. No two cows will stand at the same location.
* Lines 2..N+1: Two integers: the volume threshold and x coordinate for a cow. Line 2 represents the first cow; line 3 represents the second cow; and so on. No two cows will stand at the same location.
Output
* Line 1: A single line with a single integer that is the sum of all the volumes of the conversing cows.
Sample Input
4 3 1 2 5 2 6 4 3
Sample Output
57
分析:
首先按坐标排序,对于第i头奶牛,v[i]对总的声音产生作用的有两种情况:
(1)在i前面的牛j满足 v[j]<v[i]
(2) 在i后面的牛j满足 v[j]<=v[i]
注意:分情况的时候注意取等(即v[i]==v[j]的情况)只能加入一边讨论,否则会重复计算。
对于1,如果满足条件的牛有p头,坐标之和为sum,产生的声音为 v[i]* ( p*x[i]-sum)
问题也就变成了,按坐标顺序小到大逐个加入,求v<v[i的个数,和坐标之和,当然用两个树状数组就好了。
对于2,如果满足条件的牛有p头,坐标之和为sum,产生的声音为 v[i]* ( sum-p*s[i]),
与1类似,按坐标顺序大到小逐个加入即可。
注意使用 long long
代码如下:
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<queue> #include<vector> #include<algorithm> #define LL long long #define CLEAR(xxx) memset(xxx,0,sizeof(xxx)) using namespace std; const LL maxn=200000+5; LL n,maxv=0,c1[maxn],c2[maxn]; //c1维护坐标之和,c2维护牛的头数 inline void _read(LL &x){ char ch=getchar(); bool mark=false; for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true; for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0'; if(mark)x=-x; } inline LL lowbit(LL x){return x&-x;} struct cow{ LL v,x; bool operator < (const cow a) const { return x<a.x; } }s[maxn]; LL Sum(LL x,LL* c){ LL ans=0; while(x>0) ans+=c[x],x-=lowbit(x); return ans; } void add(LL x,LL d,LL *c){ while(x<maxv)c[x]+=d,x+=lowbit(x); } int main(){ LL i,ans=0; _read(n); for(i=1;i<=n;i++){ _read(s[i].v); _read(s[i].x); maxv=max(maxv,s[i].v); } maxv++; sort(s+1,s+1+n); for(i=1;i<=n;i++){ LL p=Sum(s[i].v-1,c2),sumx=Sum(s[i].v-1,c1); ans+=s[i].v*(p*s[i].x-sumx); add(s[i].v,s[i].x,c1); add(s[i].v,1,c2); } CLEAR(c1); CLEAR(c2); for(i=n;i>0;i--){ LL p=Sum(s[i].v,c2),sumx=Sum(s[i].v,c1); ans+=s[i].v*(sumx-p*s[i].x); add(s[i].v,s[i].x,c1); add(s[i].v,1,c2); } cout<<ans<<endl; return 0; }