P8134 [ICPC 2020 WF] Opportunity Cost|普及+

P8134 ICPC 2020 WF Opportunity Cost

题目背景

ICPC2020 WF G

题目描述

As with most types of products, buying a new phone can be difficult.

One of the main challenges is that there are a lot of different

aspects of the phone that you might care about, such as its price, its

performance, and how user-friendly the phone is.

Typically, there will be no single phone that is simultaneously the

best at all of these things: the cheapest phone, the most powerful

phone, and the most user-friendly phone will likely be different phones.

Thus when buying a phone, you are forced to make some sacrifices by

balancing the different aspects you care about against each other and

choosing the phone that achieves the best compromise (where "best"

of course depends on what your priorities happen to be). One way of

measuring this sacrifice is known as the opportunity cost ,

which (for the purposes of this problem) we define as follows.

Suppose that you have bought a phone with price x x x, performance y y y,

and user-friendliness z z z. For simplicity, we assume that these three

values are measured on a comparable numeric scale where higher is

better. If there are n n n available phones, and the values

( x i , y i , z i ) (x_i,y_i,z_i) (xi,yi,zi) represent the (price, performance, user-friendliness)

of the i th i^{\text{th}} ith phone, then the opportunity cost of your phone

is defined as

max ⁡ 1 ≤ i ≤ n ( max ⁡ ( x i − x , 0 ) + max ⁡ ( y i − y , 0 ) + max ⁡ ( z i − z , 0 ) ) \max {1 \leq i \leq n}\left(\max \left(x{i}-x, 0\right)+\max \left(y_{i}-y, 0\right)+\max \left(z_{i}-z, 0\right)\right) 1≤i≤nmax(max(xi−x,0)+max(yi−y,0)+max(zi−z,0))

Write a program that, given the list of available phones, finds a

phone with the minimum opportunity cost.

输入格式

The first line of input contains an integer n n n ( 2 ≤ n ≤ 200   000 2 \leq n \leq 200\,000 2≤n≤200000), the number of phones considered. Following that are n n n lines.

The i th i^{\text{th}} ith of these lines contains three integers x i x_i xi, y i y_i yi, and z i z_i zi,

where x i x_i xi is the price, y i y_i yi is the performance, and z i z_i zi is the

user-friendliness of the i th i^{\text{th}} ith phone ( 1 ≤ x i , y i , z i ≤ 10 9 1 \leq x_i, y_i, z_i \leq 10^9 1≤xi,yi,zi≤109).

输出格式

Output a single line containing two integers: the smallest possible

opportunity cost and an integer between 1 1 1 and n n n indicating the

phone achieving that opportunity cost. If there are multiple such

phones, output the one with the smallest index.

输入输出样例 #1

输入 #1

复制代码
4
20 5 5
5 20 5
5 5 20
10 10 10

输出 #1

复制代码
10 4

输入输出样例 #2

输入 #2

复制代码
4
15 15 5
5 15 15
15 5 15
10 10 10

输出 #2

复制代码
10 1

枚举

cost(i)表示手机i的机会成本。

cost(i,j) = m a x ( x j − x i , 0 ) + m a x ( y j − y i , 0 ) + m a x ( z j − z − i , 0 ) max(x_j-x_i,0)+max(y_j-y_i,0)+max(z_j-z-i,0) max(xj−xi,0)+max(yj−yi,0)+max(zj−z−i,0)

cost(I,j,k1,k2,k3) = k 1 ∗ ( x j − x i ) + k 2 ∗ ( y j − y i ) + k 3 ∗ ( z j − z − i ) , k 1 , k 2 , k 3 ∈ 0 , 1 k1*(x_j-x_i)+k2*(y_j-y_i)+k3*(z_j-z-i),k1,k2,k3\in{0,1} k1∗(xj−xi)+k2∗(yj−yi)+k3∗(zj−z−i),k1,k2,k3∈0,1

性质一 : c o s t ( i ) = max ⁡ j : 0 n − 1 c o s t ( i , j ) cost(i)=\max\limits_{j:0}^{n-1}cost(i,j) cost(i)=j:0maxn−1cost(i,j)

性质二 : c o s t ( i , j ) = max ⁡ k 1 , k 2 , k 3 ∈ 0 , 1 c o s t ( i , j , k 1 , k 2 , k 3 ) cost(i,j)=\max\limits_{k1,k2,k3\in {0,1}} cost(i,j,k1,k2,k3) cost(i,j)=k1,k2,k3∈0,1maxcost(i,j,k1,k2,k3)

如果: x j > x i x_j > x_i xj>xi,cost(i,j,1,k2,k3) > cost(i,j,0,k2,k3)$ 两者相减 等于 ( x j − x i ) > 0 (x_j-x_i)>0 (xj−xi)>0即前者大于后者。

如果: x j < x i x_j < x_i xj<xi,cost(i,j,1,k2,k3) < cost(i,j,0,k2,k3)$ 两者相减 等于 ( x j − x i ) < 0 (x_j-x_i)<0 (xj−xi)<0即前者小于后者。

时间复杂度 :O(8nn)

f ( k 1 , k 2 , k 3 , j ) = k 1 × x j + k 2 × y j + k 3 × z j → c o s t ( i , j , k 1 , k 2 , k 3 ) = f ( k 1 , k 2 , k 3 , j ) − f ( k 1 , k 2 , k 3 , i ) f(k1,k2,k3,j) = k1\times x_j + k2 \times y_j + k3 \times z_j \rightarrow \\ cost(i,j,k1,k2,k3)=f(k1,k2,k3,j)-f(k1,k2,k3,i) f(k1,k2,k3,j)=k1×xj+k2×yj+k3×zj→cost(i,j,k1,k2,k3)=f(k1,k2,k3,j)−f(k1,k2,k3,i)

c o s t ( i , j ) = max ⁡ k 1 , k 2 , k 3 ∈ 0 , 1 max ⁡ j : 0 n − 1 ( f ( k 1 , k 2 , k 3 , j ) − f ( k 1 , k 2 , k 3 , i ) ) = max ⁡ k 1 , k 2 , k 3 ∈ 0 , 1 ( max ⁡ j : 0 n − 1 f ( k 1 , k 2 , k 3 , j ) − f ( k 1 , k 2 , k 3 , i ) ) cost(i,j)=\max\limits_{k1,k2,k3\in {0,1}}\max\limits_{j:0}^{n-1} (f(k1,k2,k3,j)-f(k1,k2,k3,i))\\ =\max\limits_{k1,k2,k3\in {0,1}}(\max\limits_{j:0}^{n-1}f(k1,k2,k3,j)-f(k1,k2,k3,i)) cost(i,j)=k1,k2,k3∈0,1maxj:0maxn−1(f(k1,k2,k3,j)−f(k1,k2,k3,i))=k1,k2,k3∈0,1max(j:0maxn−1f(k1,k2,k3,j)−f(k1,k2,k3,i))

我们预处理出: W ( k 1 , k 2 , k 3 ) = max ⁡ j : 0 n − 1 f ( k 1 , k 2 , k 3 , j ) W(k1,k2,k3)=\max\limits_{j:0}^{n-1}f(k1,k2,k3,j) W(k1,k2,k3)=j:0maxn−1f(k1,k2,k3,j)

则上式 = max ⁡ k 1 , k 2 , k 3 ∈ 0 , 1 W ( k 1 , k 2 , k 3 ) − f ( k 1 , k 2 , k 3 , j ) =\max\limits_{k1,k2,k3\in {0,1}}W(k1,k2,k3)-f(k1,k2,k3,j) =k1,k2,k3∈0,1maxW(k1,k2,k3)−f(k1,k2,k3,j)

时间复杂度:O(8n)

代码

核心代码

cpp 复制代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>

#include <bitset>
using namespace std;

template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {
	in >> pr.first >> pr.second;
	return in;
}

template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {
	in >> get<0>(t) >> get<1>(t) >> get<2>(t);
	return in;
}

template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {
	in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);
	return in;
}

template<class T = int>
vector<T> Read() {
	int n;
	cin >> n;
	vector<T> ret(n);
	for (int i = 0; i < n; i++) {
		cin >> ret[i];
	}
	return ret;
}
template<class T = int>
vector<T> ReadNotNum() {
	vector<T> ret;
	T tmp;
	while (cin >> tmp) {
		ret.emplace_back(tmp);
		if ('\n' == cin.get()) { break; }
	}
	return ret;
}

template<class T = int>
vector<T> Read(int n) {
	vector<T> ret(n);
	for (int i = 0; i < n; i++) {
		cin >> ret[i];
	}
	return ret;
}

template<int N = 1'000'000>
class COutBuff
{
public:
	COutBuff() {
		m_p = puffer;
	}
	template<class T>
	void write(T x) {
		int num[28], sp = 0;
		if (x < 0)
			*m_p++ = '-', x = -x;

		if (!x)
			*m_p++ = 48;

		while (x)
			num[++sp] = x % 10, x /= 10;

		while (sp)
			*m_p++ = num[sp--] + 48;
		AuotToFile();
	}
	void writestr(const char* sz) {
		strcpy(m_p, sz);
		m_p += strlen(sz);
		AuotToFile();
	}
	inline void write(char ch)
	{
		*m_p++ = ch;
		AuotToFile();
	}
	inline void ToFile() {
		fwrite(puffer, 1, m_p - puffer, stdout);
		m_p = puffer;
	}
	~COutBuff() {
		ToFile();
	}
private:
	inline void AuotToFile() {
		if (m_p - puffer > N - 100) {
			ToFile();
		}
	}
	char  puffer[N], * m_p;
};

template<int N = 1'000'000>
class CInBuff
{
public:
	inline CInBuff() {}
	inline CInBuff<N>& operator>>(char& ch) {
		FileToBuf();
		ch = *S++;
		return *this;
	}
	inline CInBuff<N>& operator>>(int& val) {
		FileToBuf();
		int x(0), f(0);
		while (!isdigit(*S))
			f |= (*S++ == '-');
		while (isdigit(*S))
			x = (x << 1) + (x << 3) + (*S++ ^ 48);
		val = f ? -x : x; S++;//忽略空格换行		
		return *this;
	}
	inline CInBuff& operator>>(long long& val) {
		FileToBuf();
		long long x(0); int f(0);
		while (!isdigit(*S))
			f |= (*S++ == '-');
		while (isdigit(*S))
			x = (x << 1) + (x << 3) + (*S++ ^ 48);
		val = f ? -x : x; S++;//忽略空格换行
		return *this;
	}
	template<class T1, class T2>
	inline CInBuff& operator>>(pair<T1, T2>& val) {
		*this >> val.first >> val.second;
		return *this;
	}
	template<class T1, class T2, class T3>
	inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {
		*this >> get<0>(val) >> get<1>(val) >> get<2>(val);
		return *this;
	}
	template<class T1, class T2, class T3, class T4>
	inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {
		*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);
		return *this;
	}
	template<class T = int>
	inline CInBuff& operator>>(vector<T>& val) {
		int n;
		*this >> n;
		val.resize(n);
		for (int i = 0; i < n; i++) {
			*this >> val[i];
		}
		return *this;
	}
	template<class T = int>
	vector<T> Read(int n) {
		vector<T> ret(n);
		for (int i = 0; i < n; i++) {
			*this >> ret[i];
		}
		return ret;
	}
	template<class T = int>
	vector<T> Read() {
		vector<T> ret;
		*this >> ret;
		return ret;
	}
private:
	inline void FileToBuf() {
		const int canRead = m_iWritePos - (S - buffer);
		if (canRead >= 100) { return; }
		if (m_bFinish) { return; }
		for (int i = 0; i < canRead; i++)
		{
			buffer[i] = S[i];//memcpy出错			
		}
		m_iWritePos = canRead;
		buffer[m_iWritePos] = 0;
		S = buffer;
		int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);
		if (readCnt <= 0) { m_bFinish = true; return; }
		m_iWritePos += readCnt;
		buffer[m_iWritePos] = 0;
		S = buffer;
	}
	int m_iWritePos = 0; bool m_bFinish = false;
	char buffer[N + 10], * S = buffer;
};


class Solution {
public:
	pair<long long, int> Ans(vector<tuple<int, int, int>>& xyz) {
		long long ans = LLONG_MAX / 2;
		int inxAns = -1;
		vector<long long> g[8];
		long long llMax[8];
		const int N = xyz.size();
		for (int k1 = 0; k1 <= 1; k1++) {
			for (int k2 = 0; k2 <= 1; k2++) {
				for (int k3 = 0; k3 <= 1; k3++) {
					const int inx = 4 * k1 + 2 * k2 + k3;
					auto& f = g[inx]; f.resize(N);
					for (int i = 0; i < N; i++) {
						f[i] = (long long)k1 * get<0>(xyz[i]) + k2 * get<1>(xyz[i]) + k3 * get<2>(xyz[i]);
					}
					llMax[inx] = *max_element(f.begin(), f.end());
				}
			}
		}
		for (int i = 0; i < N; i++)
		{
			long long cur = LLONG_MIN / 2;
			for (int inx = 0; inx < 8; inx++) {
				cur = max(cur, llMax[inx] - g[inx][i]);
			}
			if (cur < ans) { ans = cur; inxAns = i; }
		}
		return { ans,inxAns };
	}
};


int main() {
#ifdef _DEBUG
	freopen("a.in", "r", stdin);
#endif // DEBUG	
	ios::sync_with_stdio(0); cin.tie(nullptr);
	CInBuff<> in; COutBuff<10'000'000> ob;	
		auto xyz = in.Read<tuple<int,int,int>>();
#ifdef _DEBUG		
		//printf("M=%d,a=%d,", M,a);
		Out(xyz, "xyz=");
		//Out(B, "B=");
		//Out(que, "que=");
		//Out(B, "B=");
#endif // DEBUG	
		auto res = Solution().Ans(xyz);	
		cout << res.first << " " << res.second + 1;
	return 0;
}

扩展阅读

算法为骨,CAD为魂
亲士工具箱:支持中望CAD2024、AutoCad2013及以上,多年承接CAD项目的精华
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

相关推荐
政企项目老覃5 小时前
边缘 AI 推理部署:安防零售场景下的模型裁剪与端侧落地实践
人工智能·程序人生·算法·性能优化·vllm
I_belong_to_jesus5 小时前
std::unique_ptr成员函数用法
c++
Tairitsu_H6 小时前
[C++] 拷贝构造还是赋值重载?类默认成员函数细节详解
开发语言·c++·类和对象
GreenTea6 小时前
发布 3 天登顶 HN:不生成一个字的模型 Jev,我把它的源码和黑料都扒了一遍
前端·后端·算法
汉克老师7 小时前
GESP2026年9月认证C++四级( 第一部分选择题(1~7题)精讲
c++·gesp·小学生·学c++编程
geats人山人海7 小时前
现代c++第二章 字符串
c++
庖丁解牛7 小时前
无穷小不是一个“神秘小数”,而是一场奔向 0 的过程
算法
idealzouhu7 小时前
现代 CMake 依赖管理详解:从构建树、Target 封装到 find_package 工作原理
c++·cmake
ZPC82107 小时前
YOLO26 识别串番茄果梗
人工智能·深度学习·算法·机器学习
景熙55238 小时前
14.Java 集合框架从入门到源码万字详解(含 ArrayList/LinkedList/HashMap 源码、泛型通配符、红黑树)
java·开发语言·数据结构·算法