POJ1990:树状数组

POJ1990

题意:

  • 牛i和j沟通,音量为abs(c[i].x-c[j].x) * max(c[i].v,c[j].v);
  • 求任意两头牛通话的音量总和

题解

  • 按牛的耳背程度从小到大排序
  • 每加入一头牛,其耳背程度一定是最大的。然后,算出与之前牛的距离之和
  • 维护距离≤xi的坐标之和sum,和数量num,则ans += (num * c[i].x - sum) * c[i].v
  • 同理可以算出距离>xi的。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
int const N = 20000 + 10;
ll n;
ll sum[N],num[N],ans;
struct Cow
{
	int v,x;
	bool operator < (const Cow& e) const{
		return v < e.v;
	}
}c[N];
ll lowbit(ll x){return x&-x;}
void add(ll c[N],ll i,ll x){
	while(i <= N){
		c[i] += x;
		i += lowbit(i);
	}
}
ll getsum(ll c[N],ll i){
	ll sum = 0;
	while(i){
		sum += c[i];
		i -= lowbit(i);
	}
	return sum;
}
int main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&c[i].v,&c[i].x);
	sort(c+1,c+1+n);
	ll tot = 0;
	for(int i=1;i<=n;i++){
		int low = getsum(num,c[i].x-1);    //比c[i].x小的数的个数
		ll s = getsum(sum,c[i].x-1);   //比c[i].x小的距之和
		ans += c[i].v * (low * c[i].x - s);    
		ans += c[i].v * ((tot - s) - c[i].x * (i - low - 1));  //比c[i].x大牛
		add(sum,c[i].x,c[i].x);
		add(num,c[i].x,1);
		tot +=  c[i].x;
	}
	printf("%lld\n",ans);
	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/88842495
今日推荐