树状数组专题最后一题,一排牛要互相说话,每个人都有一个听力入口值(我的理解是要听见东西最小的分贝),两头牛说话当然最小要等于两头牛之中听力入口值大的那个了。
本题的解法是用听力入口值最大的牛和其他比它低的牛说话,首先按照牛的听力入口值升序排序,从第一头牛开始遍历,每次第一头牛肯定是当前听力入口值最大的牛,找出其他的牛的位置和当前这头牛左右牛的个数,就可以解决这道题了。
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn = 21000;
pair<LL ,LL>c[maxn];
LL vol[maxn],loc[maxn];
int n;
int lowbit(int x)
{
return x&(-x);
}
void add(LL *bit,int i,int x)
{
for(int k=i; k<=maxn; k+=lowbit(k))
bit[k]+=x;
}
LL sum(LL *bit,int i)
{
LL sum=0;
for(int k=i; k>0; k-=lowbit(k))
sum+=bit[k];
return sum;
}
LL qsum(LL *bit,int from,int to)
{
return sum(bit,to)-sum(bit,from-1);
}
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d %d",&c[i].first,&c[i].second);
}
sort(c,c+n);
LL result=0;
for(int i=0; i<n; i++)
{
LL v=c[i].first,l=c[i].second;
LL left=qsum(vol,1,l),right=qsum(vol,l+1,maxn-1);
result+=v*((left*l-qsum(loc,1,l))+(qsum(loc,l+1,maxn-1)-right*l));
add(vol,l,1);
add(loc,l,l);
}
printf("%lld\n",result);
return 0;
}