题解:球状精灵的传说

题目链接

我们记三个维度为最大值,中间值和最小值。容易发现只需要将三个值排序,检查最大值和中间值相同,融合最小值的情况。

题意中的融合操作只会造成两种影响,一个是融合之后新最小值依然比中间值小,这并不会对答案产生贡献;还有就是融合后的新最小值超过了中间值,所以中间值成为了新的最小值,会产生新的结果。

既然我们要尽量让两个可以融合的精灵的最小值相加尽可能大,就可以维护一个大根堆,取出前两个元素来判断是否合法。使用 \(map\) 维护,以另外两个维度为关键字。由于还要维护最大值从哪里得来,所以优先队列要维护 \(pair\),以值为第一关键字,位置为第二关键字。答案遍历 \(map\) 统计即可。

复杂度 \(O(n \log^2 n)\),再次喜提最劣解。

\(Code\)

#include<bits/stdc++.h>
#define MAX 1000010
#define int long long
using namespace std;

inline int read()
{
	int s=0,w=1;
	char c=getchar();
	while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
	while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
	return s*w;
}

int n;
struct rest
{
	int a,b,c;
	#define a(i) r[(i)].a
	#define b(i) r[(i)].b
	#define c(i) r[(i)].c
	void fix(){int t=a+b+c,tt=a; a=max(max(a,b),c),c=min(min(tt,b),c),b=t-a-c;}
}r[MAX];

map<pair<int,int>,priority_queue<pair<int,int> > > q;
int maxx;
pair<int,int> ans;

signed main()
{
	n=read();
	
	for(int i=1;i<=n;++i)
	{
		a(i)=read(),b(i)=read(),c(i)=read();
		r[i].fix();
		int now=c(i)*c(i)*c(i)/4;
		if(now>maxx) maxx=now,ans.first=i,ans.second=i;
		q[make_pair(a(i),b(i))].push(make_pair(c(i),i));	
	}
	
	map<pair<int,int>,priority_queue<pair<int,int> > >::reverse_iterator iter;
	for(iter=q.rbegin();iter!=q.rend();++iter)
	{
		if(iter->second.size()<2) continue;
		pair<int,int> x=iter->second.top();
		iter->second.pop();
		pair<int,int> y=iter->second.top();
		int bb=iter->first.second;
		if(x.first+y.first>=bb)
		{
			int now=bb*bb*bb/4;
			if(now>maxx) maxx=now,ans.first=x.second,ans.second=y.second;
		}
	}
	
	if(ans.first==ans.second) cout<<0<<endl<<ans.first<<endl<<maxx;
	else cout<<1<<endl<<ans.first<<" "<<ans.second<<endl<<maxx;
	return (0-0);
}
posted @ 2022-10-19 17:13  LgxTpre  阅读(62)  评论(0编辑  收藏  举报