HDU 3552 I can do it!

【题目地址】

  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一下自己,思路不会变通呀!

【代码】

隐藏行号 复制代码 C/C++
  1. #include <cstdio>
    
  2. #include <algorithm>
    
  3. using namespace std;
    
  4. struct node{
    
  5.     int a,b;
    
  6. }set[10];
    
  7. int cmp(node s1,node s2){
    
  8.     return s1.a==s2.a?s1.b>s2.b:s1.a<s2.a;
    
  9. }
    
  10. int main(){
    
  11.     int t,ncase,n,r,i,min,max;
    
  12.     scanf("%d",&ncase);
    
  13.     for(t=1;t<=ncase;t++){
    
  14.         scanf("%d",&n);
    
  15.         for(r=0;r<n;r++)
    
  16.             scanf("%d%d",&set[r].a,&set[r].b);
    
  17.         sort(set,set+n,cmp);
    
  18.         min=set[n-1].a,max=0;
    
  19.         for(i=n-1;i>=0;i--){
    
  20.             if(set[i].b>max)
    
  21.                 max=i==0?0:set[i].b;
    
  22.             if(i>0&&min>set[i-1].a+max)
    
  23.                 min=set[i-1].a+max;
    
  24.         }
    
  25.         printf("Case %d: %d/n",t,min);
    
  26.     }
    
  27.     return 0;
    
  28. }
    

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章