[USACO] 2004 Open MooFest 奶牛集会
题目背景
MooFest, 2004 Open
题目描述
约翰的N 头奶牛每年都会参加“哞哞大会”。哞哞大会是奶牛界的盛事。集会上的活动很
多,比如堆干草,跨栅栏,摸牛仔的屁股等等。它们参加活动时会聚在一起,第i 头奶牛的坐标为Xi,没有两头奶牛的坐标是相同的。奶牛们的叫声很大,第i 头和第j 头奶牛交流,会发出\(max{Vi, Vj}\) \(×\) \(|Xi − Xj |\) 的音量,其中Vi 和Vj 分别是第i 头和第j 头奶牛的听力。假设每对奶牛之间同时都在说话,请计算所有奶牛产生的音量之和是多少。
输入输出格式
输入格式:
• 第一行:单个整数N,1 ≤ N ≤ 20000
• 第二行到第N + 1 行:第i + 1 行有两个整数Vi 和Xi.
\(1 ≤ Vi ≤ 20000; 1 ≤ Xi ≤ 20000\)
输出格式:
• 单个整数:表示所有奶牛产生的音量之和
输入输出样例
输入样例#1:
4
3 1
2 5
2 6
4 3
输出样例#1:
57
说明
朴素O(N2)
类似于归并排序的二分O(N logN)
树状数组O(N logN)
Solution
首先本着打暴力的心情先打了个\(O(N^2)\),结果数组开小了,然后改了之后就A了???
Code\((N^2)\)
#include<bits/stdc++.h>
#define lol long long
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std;
const int N=2e5+10;
void in(int &ans)
{
ans=0;int f=1; char i=getchar();
while(i<'0'||i>'9'){if(i=='-') f=-1; i=getchar();}
while(i>='0'&&i<='9') ans=(ans<<3)+(ans<<1)+i-'0',i=getchar();
ans*=f;
}
int n,m;
lol ans;
int v[N],p[N];
int main()
{
in(n);
for(int i=1;i<=n;i++) in(v[i]),in(p[i]);
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++)
ans+=(Max(v[i],v[j]))*(abs(p[i]-p[j]));
}
printf("%lld\n",ans);
return 0;
}
然后想正解,只有当一头奶牛的比其他奶牛大时才有贡献,所以我们把数据按照听力排序之后就可以消除这一点,即当前奶牛不会对后面的奶牛造成影响,因为它的听力没有后面的奶牛好
那么肯定是需要\(O(N)\)来枚举奶牛的,怎么快速算出它的贡献呢?
设num[i]为x[i]及x[i]前面的奶牛的个数,sum[i]为x[i]前面奶牛的坐标之和
都是前缀和
用一个\(log n\)的数据结构来维护,树状数组\(or\)线段树,复杂度\(O(N*logN)\)
注意:以下说的的之前都指的是在一头奶牛的坐标之前,而不是序号之前
所以每次扫到一头奶牛之后,它对答案的贡献就是
(这头奶牛之前的奶牛的数量\(*\)本头奶牛的坐标-这头奶牛之前的坐标的前缀和)\(*\) \(v[i]\)+(这头奶牛之后的坐标的前缀和-这头奶牛之后的奶牛的数量\(*\)本头奶牛的坐标)\(*\) \(v[i]\)
也就是
\]
因为我们是一边枚举一边统计,其中maxn为坐标的最大值,用sum[maxn]和num[maxn]来统计当前有多少头奶牛
先统计再插入
这里摆上树状数组的代码
Code
#include<bits/stdc++.h>
#define lol long long
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std;
const int N=2e5+10;
void in(int &ans)
{
ans=0;int f=1; char i=getchar();
while(i<'0'||i>'9'){if(i=='-') f=-1; i=getchar();}
while(i>='0'&&i<='9') ans=(ans<<3)+(ans<<1)+i-'0',i=getchar();
ans*=f;
}
int n,m,maxn;
lol ans;
struct node {
int v,x;
bool operator < (const node & a) const {
if(a.v==v) return x<a.x;
return v<a.v;
}
}sub[N];
lol num[N],sum[N];
inline int lowbit(int x)
{
return x&-x;
}
void add(int x,int a,lol *f) {
while(x<=maxn) {
f[x]+=a;
x+=lowbit(x);
}
}
lol check(int x,lol *f) {
lol ans=0;
while(x) {
ans+=f[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
in(n);
for(int i=1;i<=n;i++) in(sub[i].v),in(sub[i].x),maxn=Max(maxn,sub[i].x);
sort(sub+1,sub+1+n);
for(int i=1;i<=n;i++) {
lol size,dist;
size=check(sub[i].x-1,num);
dist=check(sub[i].x-1,sum);
ans+=sub[i].v*(size*sub[i].x-dist);
size=check(maxn,num)-check(sub[i].x,num);
dist=check(maxn,sum)-check(sub[i].x,sum);
ans+=sub[i].v*(dist-size*sub[i].x);
add(sub[i].x,sub[i].x,sum);
add(sub[i].x,1,num);
}
printf("%lld\n",ans);
return 0;
}
博主蒟蒻,随意转载.但必须附上原文链接
http://www.cnblogs.com/real-l/
[USACO] 2004 Open MooFest 奶牛集会的更多相关文章
- USACO26 moofest 奶牛集会(归并排序)
听说这题也是bzoj的3378&&poj1990,然而没有权限号交不了..poj懒得登. 题意:有n个奶牛,他们相互发出max(a[i].v,a[j].v)*abs(a[i].p-a[ ...
- usaco 奶牛集会 && 奶牛抗议
奶牛集会 Description 约翰家的N头奶牛每年都会参加“哞哞大会” .哞哞大会是世界奶牛界的盛事.集会上 的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等.当然,哞哞大叫肯定也包括在内. 奶牛 ...
- 洛谷 P2345 奶牛集会 解题报告
P2345 奶牛集会 题目背景 MooFest, 2004 Open 题目描述 约翰的N 头奶牛每年都会参加"哞哞大会".哞哞大会是奶牛界的盛事.集会上的活动很 多,比如堆干草,跨 ...
- COGS130. [USACO Mar08] 游荡的奶牛[DP]
130. [USACO Mar08] 游荡的奶牛 ★☆ 输入文件:ctravel.in 输出文件:ctravel.out 简单对比时间限制:1 s 内存限制:128 MB 奶牛们在被划 ...
- AC日记——奶牛集会 洛谷 P2345
奶牛集会 思路: 把奶牛按照v排序: 然后,每次都把奶牛放入一个集合s: 因为奶牛已经排序: 所以,每次第i次放入奶牛起作用的v就是vi: 每次ans+=(xi*sum-sumxl)*vi+(sumx ...
- luogu P2345 奶牛集会
二次联通门 : luogu P2345 奶牛集会 /* luogu P2345 奶牛集会 权值线段树 以坐标为下标, 坐标为值建立线段树 对奶牛按听力由小到大排序 对于要查的牛 每次第i次放入奶牛起作 ...
- 洛谷P2345 奶牛集会
题目背景 MooFest, 2004 Open 题目描述 约翰的N 头奶牛每年都会参加“哞哞大会”.哞哞大会是奶牛界的盛事.集会上的活动很 多,比如堆干草,跨栅栏,摸牛仔的屁股等等.它们参加活动时会聚 ...
- Luogu2345 | 奶牛集会 (树状数组)
题目背景 MooFest, 2004 Open 题目描述 约翰的 \(N\) 头奶牛每年都会参加"哞哞大会".哞哞大会是奶牛界的盛事.集会上的活动很多,比如堆干草,跨栅栏,摸牛仔的 ...
- P2345 奶牛集会andP2657 低头一族
做法是一样的 题目背景 MooFest, Open 题目描述 约翰的N 头奶牛每年都会参加“哞哞大会”.哞哞大会是奶牛界的盛事.集会上的活动很 多,比如堆干草,跨栅栏,摸牛仔的屁股等等.它们参加活动时 ...
随机推荐
- 解决如下出错:DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and willraise ValueError in 0.19.
背景:在Spyder中写几行脚本,目的是应用sklearn自带的svm(支持向量机)算法,来对其自带的digits(手写体数字)数据集进行分类,过程包括训练阶段和预测阶段.将手写体数字数据的特征数据d ...
- python集合、函数实例
集合 1.list ==>允许重复的集合,可修改 2.tuple ==>允许重复的集合,不可修改 3.dict ==> 4.set ==>不允许重复的集合,相当于不可重复的列表 ...
- http一些常见知识记录
HTTP请求包(浏览器信息) 我们先来看看Request包的结构, Request包分为3部分,第一部分叫Request line(请求行), 第二部分叫Request header(请求头),第三部 ...
- YUM工具使用
一.yum命令概述: 1.简介: yum命令时在Fedora和RedHat以及SUSE中基于rpm的软件包管理器,它可以使系统管理人员交互和自动化地更细与管理RPM软件包,能够从指定的服务器自动下载R ...
- 003---生成器 & 迭代器
生成器 & 迭代器 列表生成式 现在有个需求,列表[1, 2, 3, 4, 5, 6, 7, 8, 9],将列表里的每个值加1. 二逼青年版 a = [1, 2, 3, 4, 5, 6, 7, ...
- PATA1034题解
题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805456881434624 参考:算法笔记(胡凡)10.3.1 # ...
- CS61B sp2018笔记 | Lists
Lists csdn同作者原创地址 1. IntLists 下面我们来一步一步的实现List类,首先你可以实现一个最简单的版本: public class IntList { public int ...
- sqoop 的使用 -20160410
1 导入导出数据库 1)列出mysql数据库中的所有数据库命令 # sqoop list-databases --connect jdbc:mysql://localhost:3306/ - ...
- 接口测试工具postman(三)添加断言
每个用例执行完成后,可以通过添加断言来判断返回结果是否正确,即表示用例执行是否成功. 官方说明文档:https://learning.getpostman.com/docs/postman/scrip ...
- 在 C/C++ 中使用 TensorFlow 预训练好的模型—— 直接调用 C++ 接口实现
现在的深度学习框架一般都是基于 Python 来实现,构建.训练.保存和调用模型都可以很容易地在 Python 下完成.但有时候,我们在实际应用这些模型的时候可能需要在其他编程语言下进行,本文将通过直 ...