您的位置:首页 > 其它

【NOIP2016提高A组集训第8场11.5】心理学概论

2016-11-05 14:37 369 查看

Description

上了大学之后,小W和小Z一起报了一门虐课,在课本上遇到了一份关于嫉妒的案例。

很久很久以前,森林里住着一群兔子。

其中有三只兔子,第一只兔子喜欢吃萝卜,第二只兔子喜欢吃青菜,第三只兔子喜欢吃三文鱼中卷寿司。

有一天,他们收集了 n 个篮子的食物,其中每个篮子里恰好装了一只萝卜,一捆青菜和一个三文鱼中卷寿司,每个食物都有一个美味度。然后他们打算分吃篮子里的食物。如果第一只兔子得到了一些篮子,那么他只会吃每个篮子里面的胡萝卜,然后它获得的美味度即为它吃到的美味度最大的胡萝卜。同理第二只兔子只会吃青菜,第三只兔子只吃三文鱼中卷寿司,同时他们也分别能获得一个美味度。

出于嫉妒心,其余的没有食物的兔子希望计算,如果给这三只兔子划分篮子,使得他们三人获得的美味值之和最小。注意每个篮子是最小的划分单位,不能把篮子里的食物拿出来和放入新食物。如果一个兔子没有得到任何篮子,那么它获得的美味度为0。

Solution

比赛的时候,我直接打上了贪心,但是很快就举出了反例。然后,我打了7个贪心取最小值。结果还是错的。

我想了一下双二分,二分a的位置,然后在里面套上一个二分b的位置,然后O(n)求出c,更新答案。

有一群人打暴力竟然过了这些水数据。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll i,j,k,l,n,m,ans1,ans2,ans3,r,mid,lo,ro,mido;
ll ans,x,y,z,t,o;
bool bz;
const int maxn=100007;
struct node{
ll a,b,c,d;
}a[maxn];
bool cmp1(node x,node y){return x.a<y.a||x.a==y.a&&x.b<y.b||x.a==y.a&&x.b==y.b&&x.c<y.c;}
int main(){
freopen("psy.in","r",stdin);
freopen("psy.out","w",stdout);
scanf("%lld",&n);
fo(i,1,n){
scanf("%lld%lld%lld",&a[i].a,&a[i].b,&a[i].c);
ans1=max(a[i].a,ans1);ans2=max(a[i].b,ans2);ans3=max(ans3,a[i].c);
a[i].d=min(a[i].a,min(a[i].b,a[i].c));
}
ans=min(ans1,min(ans2,ans3));
sort(a+1,a+1+n,cmp1);
l=0,r=n;
while(l<r){
mid=(l+r)/2;
lo=0,ro=n;
bz=1;
while(lo<ro){
mido=(lo+ro)/2;
if(mido==mid){
if(mido+1!=r)mido++;
else if(mido-1!=l)mido--;
else{
bz=0;
break;
}
}
k=0;
fo(i,1,n){
if(a[i].a<=a[mid].a)continue;
if(a[i].b<=a[mido].b)continue;
if(a[i].c>k)k=a[i].c;
}
ans1=a[mid].a+a[mido].b+k;
if(ans1<ans){
ans=ans1;
bz=1;
ro=mido;
}
else lo=mido+1;
}
if(bz)r=mid;else l=mid+1;
}
k=0;
fo(i,1,n){
if(a[i].a<=a[l].a)continue;
if(a[i].b<=a[lo].b)continue;
if(a[i].c>k)k=a[i].c;
}
ans=min(ans,a[l].a+a[lo].b+k);
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: