牛客网[CF1043] Train Hard, Win Easy(前缀和好题)

本文解析了一道关于n人做题,m对人不能组队的优化问题。通过理解题意,提出利用排序和前缀和技巧降低时间复杂度,最终给出nlogn的解决方案。关键在于理解题目中如何根据时间差分配队伍组合,以求得最小总答题时间。
摘要由CSDN通过智能技术生成

Train Hard, Win Easy

原题链接


首先这道题最大的难点就是理解题意,各种翻译软件翻译出来的几乎完全看不懂,只能慢慢的借助样例解释慢慢的来了解题意。

题意大概如下:

总共有两道题,给你n个人做每道题目的时间,之后是m个关系,这m对人无法组队,两道题目两个人组队一人一道,每次组队的时候要使总时间最少,求每个人和其他能组队的人组队的得分和
数据范围:2<=n<=3e5,0<=m<=3e5

首先考虑暴力是否可行
要求没两个人的两两组合,n^2,显然不行

再开始想正解

依据题意
我们先假设m为0
那么

a n s i = ∑ i n m i n ( a i + b j , b i + a j ) ansi= \sum_{i}^{n} min(ai+bj,bi+aj) ansi=inmin(ai+bj,bi+aj)

也就是说
当ai+bj<bi+aj时对答案的贡献是ai+bj
反之则是bi+aj

我们将其移下项
bj-aj<bi-ai时对答案的贡献是ai+bj
现在已经看到正解的尾巴了

如果我们将每个人的bi-ai进行从小到大排序,在这个人前面的人(记为j)的bj-aj都会小于bi-ai

那么对答案的贡献就是ai+bj,也就是前面所有人的bj都和ai进行配对,然后我们只要借助前缀和进行优化
就可以求出前i-1个人(排好序的数组里的编号)和i组队的最小答题时间和,即为sumb+ai*(i-1)
后面的同理,应该为suma+ai*(n-i)
这里的suma是从n到1的a[i]的前缀和
sumb是1到n的b[i]的前缀和

然后最后减去不能组队的情况,就解决了

代码如下(时间复杂度nlogn):

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long 
using namespace std;
const int maxn=3000005;
int n,m;
ll a[maxn],b[maxn];
struct num_node{
	ll num;
	int id;
}s[maxn];
ll ans[maxn];
bool cmp(num_node a,num_node b){
	return a.num<b.num;
}
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i){
		ll x,y;
		scanf("%lld %lld",&x,&y);
		a[i]=x;b[i]=y;
		s[i].num=y-x;
		s[i].id=i;
	}
	sort(s+1,s+n+1,cmp);
	ll suma=0,sumb=0;//这里必须开long long 
	for(int i=1;i<=n;++i){
		ans[s[i].id]+=a[s[i].id]*(i-1)+sumb;
		sumb+=b[s[i].id];
	}
	for(int i=n;i>=1;--i){
		ans[s[i].id]+=b[s[i].id]*(n-i)+suma;
		suma+=a[s[i].id];
	}
	while(m--){
		ll x,y;
		scanf("%lld %lld",&x,&y);
		ans[x]-=min(b[x]+a[y],b[y]+a[x]);
		ans[y]-=min(b[x]+a[y],b[y]+a[x]);
	}
	for(int i=1;i<=n;++i){
		printf("%lld",ans[i]);
		if(i!=n)printf(" ");
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
win11 安卓 0x80073cf3 错误通常是指在安装或更新某些应用程序时出现的问题。这个错误代码表示某些文件或组件存在冲突或已损坏。要解决这个问题,可以尝试以下几种方法: 1. 清理磁盘空间:确保你的设备有足够的磁盘空间来安装或更新应用程序。删除不需要的文件或程序可以释放磁盘空间。 2. 重启设备:有时候,重新启动设备可以解决一些临时问题。尝试重新启动你的设备,然后再次尝试安装或更新应用程序。 3. 检查网络连接:确认你的设备连接到可靠的网络。弱或不稳定的网络连接可能导致安装或更新失败。尝试连接到其他网络,或者重启你的网络设备。 4. 清理应用程序缓存:打开设置菜单,找到应用程序管理器或应用程序设置,然后找到出现错误的应用程序。点击该应用程序,并清理它的缓存。然后尝试重新安装或更新应用程序。 5. 更新操作系统:确保你的操作系统是最新的版本。有时候旧的操作系统版本可能导致应用程序安装或更新出错。检查当前的系统更新,并安装任何可用的更新。 如果以上方法都无法解决问题,你可以考虑联系设备的制造商或微软客户支持寻求进一步的帮助。他们可能能够提供针对特定设备或操作系统的解决方案。记住提供尽可能详细的信息,例如你正在尝试安装的应用程序名称和版本,以及你所使用的设备型号和操作系统版本等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值