当前位置: 首页 > article >正文

E. Train Hard, Win Easy(数学推导 + 前缀和)

Problem - E - Codeforces

 

这是一个有关竞赛编程的问题。Zibi 是一名竞赛编程教练,有 n 名选手想要备战。培训比赛具有一些不同寻常的规则——每个团队有两名成员和两个问题,每个选手都会编写其中一个问题的代码。当然,一个团队中的人将编写不同的问题。

评分规则也不是典型的。第一个问题总是一个实现问题:你必须非常快地实现某个众所周知的算法,而你的打字时间将被评分。第二个问题是一个可怕的几何任务,你只需要在合理的时间内得到它的通过。在这里,你的代码长度和难度很重要。之后,Zibi 将为每个方案给出一些罚分(可能是负数),团队的最终得分是它们的总和(得分越少,就越好)。

我们知道,当第 i 位选手编写第一个任务时,他总是会得到 xi 分,编写第二个任务时,他总是会得到 yi 分。我们可以假设,所有选手都知道彼此的技能,并在比赛期间分配问题,以最小化他们的最终得分。请记住,在比赛中,每个人都只编写一个问题。

Zibi 希望所有选手彼此之间进行比赛。然而,有 m 对人真的不喜欢合作,他们绝对不会在一起写比赛。尽管如此,教练将为所有可能的人组成团队,这些人不会互相厌恶。对于每个参与者,教练都感兴趣,他或她所训练的所有团队的得分总和是多少?

输入包含若干行:第一行包含两个整数 n 和 m(2≤n≤300000,0≤m≤300000)——参赛者数量和不想一起写比赛的人数。接下来的 n 行,每行包含两个整数 xi 和 yi(−109≤xi,yi≤109)——第 i 位选手在第一个问题和第二个问题上获得的分数。保证没有两个人既有 xi 又有 yi 相同的情况。最后的 m 行中,每行包含两个整数 ui 和 vi(1≤ui,vi≤n,ui≠vi)——不想在同一个团队中的人的索引。每个无序索引对最多出现一次。

输出 n 行,按照它们在输入中出现的顺序,输出所有参与者的得分总和。

Examples

input

Copy

3 2
1 2
2 3
1 3
1 2
2 3

output

Copy

3 0 3 

input

Copy

3 3
1 2
2 3
1 3
1 2
2 3
1 3

output

Copy

0 0 0 

input

Copy

5 3
-1 3
2 4
1 1
3 5
2 2
1 4
2 3
3 5

output

Copy

4 14 4 16 10 

题解:
除了m种不会组队的,其他一定会组队,单个枚举的话n^2肯定会t,

那么我们可不可以先算出所有的贡献(假设没有之间不组队的人),所有人都相互组队

但这时又会有一个问题,我们如何确定组队时,谁写第一题谁写第二题?

假设我们设

a1 a2

b1 b2

如果a写第一题更优应该满足

a1 + b2 < b1 + a2

变形就成了

a1 - a2 < b1 - b2

我们按照这个排序一下,开始找最优

假设此时遍历到i,i的下标是id(原来的下标)

由于每一个人的顶多会和n - 1个人组队,

贡献其实就是统计前i - 1个人怎么选,(n - i)个人怎么选

由于我们排过序,前面i - 1个人,肯定选第一个比较好,(注意此时都是在和第i个比),前i-1的第二个由i选比较好

对于(n - i)个,排在i后面的,相比选(n - i)的第一个肯定不如选让i选第一个,那么(n - i)的都选第二个

当然对于不能组队的也要减去其贡献,每次记录id,代表其已经选过

然后看是否有和id不能一起组队的,

如果有又分为两种情况

1.被标记过,说明这个人在前面,说明当时肯定这个人选的是第一个,那么id选的就是第二个,减去贡献

2.刚好与第一种相反

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
int mod = 1e9 + 7;
int n,m;
struct node
{
	int one,two,id;
}a[300050];
int one[300050];
int two[300050];
int last[300005];
vector<int> p[300050];
bool cmp(node a,node b)
{
	return a.one - a.two < b.one - b.two;
}
int ans[300050]; 
void solve()
{
	cin >> n >> m;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i].one >> a[i].two;
		a[i].id = i;
		one[i] = a[i].one;
		two[i] = a[i].two;
	}
	for(int i = 1;i <= m;i++)
	{
		int x,y;
		cin >> x >> y;
		p[x].push_back(y);
		p[y].push_back(x);
	}
	sort(a + 1,a + 1 + n,cmp);
	for(int i = n;i >= 1;i--)
	last[i] = last[i + 1] + a[i].two;
	map<int,int> f;
	int pre = 0;
	for(int i = 1;i <= n;i++)
	{
		int id = a[i].id;
		f[id] = 1;
		ans[id] += pre;
		ans[id] += (i - 1)*a[i].two;
		ans[id] += last[i + 1];
		ans[id] += (n - i)*a[i].one;
		for(int j = 0;j < p[id].size();j++)
		{
			int now = p[id][j];
			if(f[now])
			{
				ans[id] -= one[now];
				ans[id] -= two[id];
			}
			else
			{
				ans[id] -= one[id];
				ans[id] -= two[now];
			}
		}
		pre += a[i].one;
	}
	for(int i = 1;i <= n;i++)
	cout << ans[i] <<" ";
}
signed main()
{
	ios::sync_with_stdio(0 );
	cin.tie(0);cout.tie(0);
	int t = 1;
//	cin >> t;
	while(t--)
	{
		solve(); 
	}
}


http://www.kler.cn/a/17019.html

相关文章:

  • Python——NumPy库的简单用法,超级详细教程使用
  • 【CVPR2024】2024年CVPR的3D 目标检测的综述(还在补充中)
  • JavaScript 观察者设计模式
  • Cyberchef配合Wireshark提取并解析HTTP/TLS流量数据包中的文件
  • 【算法一周目】双指针(2)
  • 传奇996_21——龙岭事件
  • JAVA-实现简易图书管理系统
  • leetcode 面试题 02.04. 分割链表
  • YonLinker连接集成平台构建新一代产业互联根基
  • babysql
  • JavaWeb学习------Servlet
  • Java基本数据类型以及包装类型的常量池技术
  • Java中线程池的介绍、构造方法及优势
  • 电子工程师是怎么练成的
  • 数据结构与算法之链表: Leetcode 141. 环形链表 (Typescript版)
  • 谷粒商城二十四Sentinel限流熔断降级
  • 用于scATAC-seq有监督分类的Cellcano
  • 【LeetCode刷题记录】数组专题
  • Python小姿势 - Python面向对象
  • 《基于深度学习模型的非接触式面部视频记录技术用于心房颤动的检测》阅读笔记
  • 「Codeforces」B. Avoid Local Maximums
  • Redis之五大基本的数据类型:字符串String 散列hashes 列表 lists 集合sets 有序集合sorted sets 基础命令讲解
  • 学生台灯什么牌子好对眼睛好?专业护眼灯的学生台灯分享
  • 【AI工具】bing chat 使用--三种模式+撰写功能
  • gradle Task 详解
  • 什么是Filter?