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++**实现。

相关推荐
hoiii18715 小时前
matlab基础贝叶斯变换的压缩感知
算法·机器学习·matlab
不会C语言的男孩15 小时前
C++ Primer Plus 第2章:开始学习C++
开发语言·c++
c2385615 小时前
MySrting的模拟实现
开发语言·c++·算法
周杰伦fans15 小时前
DeepSeek 智能效果全景展示
算法
Rabitebla15 小时前
C++ 继承详解(下):默认成员函数、虚继承底层与设计取舍
c语言·开发语言·数据结构·c++·算法·leetcode
爱喝水的鱼丶16 小时前
SAP-ABAP:条件判断与循环控制语句(7篇)第七篇:性能优化:条件与循环代码的常见性能瓶颈与优化方案
学习·算法·性能优化·sap·abap
吃好睡好便好21 小时前
提取矩阵某一行或某一列元素
开发语言·人工智能·线性代数·算法·matlab·矩阵
wljy11 天前
二、进制状态转换
linux·运维·服务器·c语言·c++
云泽8081 天前
笔试算法 -位运算篇(二):从唯一字符到消失数字
c++·算法·位运算