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. }
    

 

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