【题目地址】
http://acm.hdu.edu.cn/showproblem.php?pid=3552
【题目大意】
每个点有两个属性,a和b;将n(n<=100000)个点分成两个集合A和B(集合允许为空),求A集合中点的a属性最大值和B集合中点的b属性的最大值之和最小。
【解题思路】
题目是英文叙述的,有点难理解。因为比赛时自己想错了,所以把这道简单题贴出来。
简单的做法是按a属性对所有点排序,按b属性扫描,只需要min(a[i]+max(b[j],i+1<=j<=n))即可。
证明:集合是按a属性值递增的,a[r]+b[j]<=a[i]+b[j],(r<=i),没有必要再去比较。
上述的方法是正向扫描(我当时的想法),时间复杂度O(n^2),果断TLE,囧···。。
逆向扫描,只需维护max(b[j],i+1<=j<=n)即可,时间复杂度O(n)。
哎!BS一下自己,思路不会变通呀!
【代码】
#include <cstdio>
#include <algorithm>
using namespace std;
struct node{
int a,b;
}set[10];
int cmp(node s1,node s2){
return s1.a==s2.a?s1.b>s2.b:s1.a<s2.a;
}
int main(){
int t,ncase,n,r,i,min,max;
scanf("%d",&ncase);
for(t=1;t<=ncase;t++){
scanf("%d",&n);
for(r=0;r<n;r++)
scanf("%d%d",&set[r].a,&set[r].b);
sort(set,set+n,cmp);
min=set[n-1].a,max=0;
for(i=n-1;i>=0;i--){
if(set[i].b>max)
max=i==0?0:set[i].b;
if(i>0&&min>set[i-1].a+max)
min=set[i-1].a+max;
}
printf("Case %d: %d/n",t,min);
}
return 0;
}