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;
}
都看到这了,真的不点个赞吗(>ω<*)