pku2010 Moo University - Financial Aid 二分法的高级应用

pku2010 Moo University - Financial Aid 二分法的高级应用

题意大概说下
N头奶牛想上大学,每个奶牛有一个SAT分数和一个助学金数目。奶牛大学只能提供M个名额以及K助学金数目。求一种分配方案使得奶牛大学录取的牛中SAT分数在中位数上的分数最大。
思路:
可以对奶牛的分数排序后二分确定中位数。开两个数组,datas,datac,前者按照奶牛分数排序,后者按照奶牛助学金数目排序。二分枚举中位数,然后进行验证:
按照datac从低到高顺序在总和小于等于k的情况下统计处落在左区间的数目left和右区间的数目right
如果left>m/2&&right>m/2,当前方案可行,尝试中位数更大的方案
如果left<m/2&&right<m/2,则不可能
如果left<m/2&&right>m/2,中点应该向右移动
如果left>m/2&&right<m/2,中点应该向左移动
注意考虑中点的覆盖情况。
还有,可能调整到最后也没法满足条件,那么也输出-1
具体看程序吧
 1  # include  < cstdio >
 2  using   namespace  std;
 3  # include  < algorithm >
 4  # include  < cstring >
 5  int  n,c,f;
 6  struct  node
 7  {
 8      int  s,c;
 9      int  id;
10  }cows[ 100005 ],cowc[ 100005 ];
11  int  rank[ 100005 ];
12  bool  cmps(node a,node b)
13  {
14       return  a.s < b.s;
15  }
16  bool  cmpc(node a,node b)
17  {
18       return  a.c < b.c;
19  }
20  int  chk( int  pos)
21  {
22       int  left = 0 ,right = 0 ,tf = f;
23       bool  mid = false ;
24       for ( int  i = 0 ;i < c;i ++ )
25         if (rank[cowc[i].id] < pos && left < n / 2 )
26            if (tf >= cowc[i].c)
27              left ++ ,tf -= cowc[i].c;
28            else   break ;
29         else   if (rank[cowc[i].id] == pos &&! mid)
30            if (tf >= cowc[i].c)
31               mid = true ,tf -= cowc[i].c;
32            else    break ;
33         else   if (rank[cowc[i].id] > pos && right < n / 2 )
34            if (tf >= cowc[i].c)
35               right ++ ,tf -= cowc[i].c;
36            else   break ;
37       if (left >= n / 2 && right >= n / 2 && mid)  return   0 ;
38       else   if (left >= n / 2 return   1 ;
39       else   if (right >= n / 2 return   - 1 ;
40       else   if (left < n / 2 && right < n / 2 return   - 2 ;
41  }
42  int  main()
43  {
44      scanf( " %d%d%d " , & n, & c, & f);
45       for ( int  i = 0 ;i < c;i ++ )
46      {
47        scanf( " %d%d " , & cows[i].s, & cows[i].c);
48        cows[i].id = i;
49      }
50      memcpy(cowc,cows, sizeof (cows));
51      sort(cows,cows + c,cmps);
52      sort(cowc,cowc + c,cmpc);
53     /*   printf("sorted by s\n");
54         for(int i=0;i<c;i++)
55           printf("(%d,%d)\n",cows[i].id,cows[i].s);
56      printf("\n");
57      printf("sorted by c\n");
58         for(int i=0;i<c;i++)
59           printf("(%d,%d)\n",cowc[i].id,cowc[i].c);
60      printf("\n"); */
61       int  s = n / 2 ,e = c - 1 - n / 2 ;
62       for ( int  i = 0 ;i < c;i ++ )
63        rank[cows[i].id] = i;
64       while (s <= e)
65      {
66          int  mid = (s + e) / 2 ;
67          switch (chk(mid))
68         {
69             case   - 1 :
70                 s = mid + 1 ;
71                  break ;
72             case   1 :
73                 e = mid - 1 ;
74                  break ;
75             case   0 :
76                 s = mid + 1 ;
77                  break ;
78             case   - 2 :
79                 printf( " -1\n " );
80                  return   0 ;
81         };
82      }
83       if (chk(s - 1 ) == 0 )
84        printf( " %d\n " ,cows[s - 1 ].s);
85       else
86        printf( " -1\n " );
87      //    system("pause");
88         return   0 ;
89  }
90 


你可能感兴趣的:(pku2010 Moo University - Financial Aid 二分法的高级应用)