MooFest POJ-1990 (树状数组)

题目

传送门

问题描述

每年,农夫约翰的N(1 <= N <= 20,000)只牛会参加“MooFest”,一个来自世界各地的牛的社交聚会。 MooFest有许多活动,包括干草堆积,篱笆跳跃,把尾巴钉在农夫的身上...当奶牛都站在同一个地方排队,他们会大声喊叫,吼声几乎震耳欲聋。事实上,每年参加了这个活动后,一些奶牛已经失去了部分听力。
每个奶牛具有耳背值v(i)(在1..20,000的范围内)。如果一头牛向牛i吼叫,她必须使用至少是两头母牛之间距离的v(i)倍的声音,以便被牛i听到。如果两个奶牛i和j想要交谈,她们必须以等于她们之间的距离乘以max(v(i),v(j))的音量说话。
假设N头奶牛中的每头奶牛都站在直线上(每头奶牛在1..20,000范围内的某个独特x坐标),每对奶牛都使用尽可能小的声音进行谈话。
计算所有N(N-1)/ 2对正在说话的奶牛产生的所有声音的总和。

输入格式:

*第1行:单个整数,N
*第2到N + 1行:两个整数:牛的耳背值v和x坐标。第2行代表第一头牛;第3行表示第二头牛;等等。没有两头牛会站在同一个位置。

输出格式:

*第1行:仅含单个整数,表示所有牛互相吼叫的所有声音的总和。

样例输入:

4
3 1
2 5
2 6
4 3

样例输出:

57

思路

读题,不难想到要定义一个结构体去存储每头的v和pos(position位置),再将结构体按v从小到大排序,计算某头时,只考虑v比它小的其他
打暴力显然会TLE(别问我怎么知道的,不信你可以去试试↓↓↓)

暴力coed君
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define int long long
#define inf 0x3f
#define INF 0x3f3f3f3f
#define mst(a,b) memset(a,b,sizeof(a))
#define Elaina 0
const int N=20005;
int a[N],b[N],c[N],n,m,ans=0;
struct point{
	int v,pos;
	bool operator < (const point &op) const{
		if(v==op.v){
			return pos<op.pos;
		}else{
			return v<op.v;
		}
	}
}p[N];
int Iabs(int x){
	return x>=0?x:-x;
}
signed main(){
	ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
	cin>>n;
    for(int i=1;i<=n;i++){
		cin>>p[i].v>>p[i].pos;
	}
	sort(p+1,p+1+n);
	for(int i=1;i<=n;i++){
		for(int j=i;j>0;j--){
			ans+=Iabs(p[i].pos-p[j].pos)*p[i].v;
		}
	}
	cout<<ans;
    return Elaina;
}
因此我们考虑另一种思路,也就是树状数组。

分析样例:

(结构体排序后)

声音v 2 2 3 4
坐标pos 5 6 1 3

ans=2 * (6-5)+3 * (5-1)+3 * (6-1)+4 * (5-3)+4 * (6-3)+4 * (3-1)
  =57

观察可得出

变量 含义
v 该牛声音
pos 该牛坐标
num1 sum1 坐标值比该牛小的数目及坐标之和
num2 sum2 坐标值比该牛大的数目及坐标之和

该牛的贡献=v * (pos * num1-sum1+sum2-pos * num2)

举个例子:

声音v 2 2 4 5 5 6
坐标pos 8 2 6 3 4 7

对于第⑤只牛来说:

比它小的 5 * (4-3)+5 * (4-2)
比它大的 5 * (8-4)+5 * (6-4)
合起来化简为 5 * (2 * 4-5+14-2 * 4)

我们可以一个二维数组表示牛的坐标之和以及牛的数量之和。
于是代码就是↓

Elaina's code

Elaina's code
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define int long long
#define inf 0x3f
#define INF 0x3f3f3f3f
#define mst(a,b) memset(a,b,sizeof(a))
#define Elaina 0
const int N=20005;
int a[N],b[N],c[5][N],n,m,ans=0;//c[1]记录头数 c[2]记录距离 
struct point{
	int v,pos;
	bool operator < (const point &op) const{
		if(v==op.v){
			return pos<op.pos;
		}else{
			return v<op.v;
		}
	}
}p[N];
int lowbit(int x){
	return x&(-x);
} 
void add(int d,int x,int k){
	while(x<=N){
		c[d][x]+=k;
		x+=lowbit(x);
	}
}
int getsum(int d,int x){
	int sum=0;
	while(x>0){
		sum+=c[d][x];
		x-=lowbit(x);
	}
	return sum;
}
signed main(){
	ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
	cin>>n;
    for(int i=1;i<=n;i++){
		cin>>p[i].v>>p[i].pos;
	}
	sort(p+1,p+1+n);
	int tot=0;
	for(int i=1;i<=n;i++){
		int x=p[i].pos;
		tot+=x;//记录坐标和
		add(1,x,1);
		add(2,x,x);
		int s1=getsum(1,x),s2=getsum(2,x);//s1表示i牛前面的牛的头数,s2表示i牛前面的牛的坐标和
		int temp1=s1*x-s2,temp2=tot-s2-x*(i-s1);//temp1表示i牛左边的坐标差,temp2表示i牛右边的坐标差 
		ans+=(temp1+temp2)*p[i].v;
	}
	cout<<ans;
    return Elaina;
}

都看到这了,真的不点个赞吗(>ω<*)

posted @ 2024-02-19 09:13  Elaina_0  阅读(56)  评论(9编辑  收藏  举报
浏览器标题切换
浏览器标题切换end