luogu P8585 球状精灵的传说 题解

题目大意

给定 \(n\) 个精灵的三维幅度 \(\{r_{1,i},r_{2,i},r_{3,i}\}\),任意两个精灵若在三个幅度中有两个相同(这里可以乱序)则可以将剩下的一位相加组合起来。组合过的精灵不能再组合。求精灵最大可能声望值。定义声望值为 \(\rho=\lfloor\frac{1}{4}\min\{r_{1,i},r_{2,i},r_{3,i}\}\rfloor\)

Solution

首先我们知道两个精灵如果能够组合那么组合得来的精灵一定不劣于两个分开的精灵。

考虑什么时候两个精灵组合起来会优于原来两个分开的精灵:容易发现需要使得 \(\min\{r_{1,i},r_{2,i},r_{3,i}\}\) 的值变化。因此只有当两个较大面相同时,将最小面相加,组合才能有效。

二分出符合条件的(即两个较大面相同)的精灵,取其中最小一维最大的即可。

Code

#include<bits/stdc++.h>
#define HohleFeuerwerke using namespace std
//#pragma GCC optimize(3,"Ofast","-funroll-loops","-fdelete-null-pointer-checks")
//#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#define int long long
HohleFeuerwerke;
inline int read(){
	int s=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) s=s*10+c-'0';
	return s*f;
}
inline void write(int x){
	if(x<0) putchar('-'),x=-x;
	if(x>=10) write(x/10);
	putchar('0'+x%10);
}
const int MAXN=1e6+5,INF=0x7f7f7f7f7f;
int n;
struct node{
	int x,y,z,org;
}t[MAXN];
int ans,anstype,ans1,ans2,tmp1,tmp2;
inline int mymin(int x,int y,int z){
	return min(x,min(y,z));
}
inline int mymax(int x,int y,int z){
	return max(x,max(y,z));
}
inline bool cmp(node a,node b){
	if(a.x!=b.x) return a.x>b.x;
	else if(a.y!=b.y) return a.y>b.y;
	else return a.z>b.z;
}
inline int calc(node a){
	int tmp=mymin(a.x,a.y,a.z);
	return floor(0.25*tmp*tmp*tmp);
}
signed main()
{
	n=read();
	for(int i=1;i<=n;i++){
		int a=read(),b=read(),c=read();
		t[i].x=mymax(a,b,c);
		t[i].z=mymin(a,b,c);
		t[i].y=a+b+c-t[i].x-t[i].z;
		t[i].org=i;
	}
	sort(t+1,t+n+1,cmp);
	for(int i=1;i<=n;i++){
		int l=1,r=n;node best=t[i];
		bool type=false;
		int lok,rok;
		while(l<r){
			int mid=(l+r)/2;
			if(cmp(t[mid],node{t[i].x,t[i].y,INF})) l=mid+1;
			else r=mid-1;
		}
		lok=l,l=1,r=n;
		while(l<r){
			int mid=(l+r)/2;
			if(cmp(t[mid],node{t[i].x,t[i].y,0})) l=mid+1;
			else r=mid-1;
		}
		rok=l;
		for(int j=lok;j<=rok;j++){
			if(t[j].x==t[i].x&&t[j].y==t[i].y&&t[j].z!=t[i].z){
				best.z+=t[j].z,type=true;
				if(calc(best)>ans){
					anstype=type;ans=calc(best);
					ans1=t[i].org,ans2=t[j].org;
				}
				break;
			}
		}
		if(calc(best)>ans){
			anstype=type;ans=calc(best);
			ans1=t[i].org,ans2=0;
		}
	}
	write(anstype),puts("");
	if(anstype) write(ans1),putchar(' '),write(ans2),puts("");
	else write(ans1),puts("");
	write(ans),puts("");
	return 0;
}
posted @ 2022-10-23 00:46  _HofFen  阅读(69)  评论(0编辑  收藏  举报