【題目地址】
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;
}