码迷,mamicode.com
首页 > 其他好文 > 详细

codeforece Round#311

时间:2015-07-01 09:56:23      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:

B题

给我们n,m ,  m表示茶壶的容量

接下来2*n个数字,表示茶杯的容量,将这些茶杯分给n个男孩和n个女孩

可以倒x毫升的茶水给每个女孩,那么就要倒2x毫升的茶水给男孩,当然了,茶杯要装的下,且茶壶的水足够多

问最多能倒多少毫升?

思路:将茶杯按容量从下到大排序,那么前n个茶杯一定分给女孩,后n个茶杯分给男孩。那么只要将第一个茶杯的容量作为上界,0作为下界,二分枚举x,

每次统计后n个茶杯的容量是不是>=2x,如果是,那么说明该容量是可行的。 但是最终的数据测试却错了, 因为精度要达到1e-11才能正确,不知道为什么

技术分享
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 #pragma warning(disable:4996)
15 typedef long long LL;                   
16 const int INF = 1<<30;
17 const double eps = 1e-11;
18 /*
19 
20 
21 */
22 int a[200000 + 10];
23 int main()
24 {
25     int n, w;
26     while (scanf("%d%d", &n,&w) != EOF)
27     {
28         int m = 2 * n;
29         for (int i = 0; i < m; ++i)
30         {
31             scanf("%d", &a[i]);
32         }
33         sort(a, a + m);
34         double low = 0, high = a[0], mid;
35         int cnt;
36         double tmp;
37         while (high - low >= eps)
38         {
39             mid = (high + low) / 2;
40             cnt = 0;
41             for (int i = 0; i < m; ++i)
42             if (mid * 2 <= a[i])
43                 cnt++;
44             if (cnt >= n)
45             {
46                 tmp = mid * 3 * n;
47                 if (tmp<w)
48                     high = mid;
49                 else
50                     low = mid;
51             }
52             else
53                 high = mid;
54         }
55         printf("%f\n", mid * 3 * n);
56         
57     }
58     return 0;
59 }
View Code

比完看了别人代码才知道,有更简单的方法, 只要去w/3/n, a[0], a[n]/2 的最小值就好了

技术分享
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 #pragma warning(disable:4996)
15 typedef long long LL;                   
16 const int INF = 1<<30;
17 const double eps = 1e-11;
18 /*
19 
20 
21 */
22 int a[200000 + 10];
23 int main()
24 {
25     int n, w;
26     double ans = 0;
27     while (scanf("%d%d", &n,&w) != EOF)
28     {
29         int m = 2 * n;
30         for (int i = 0; i < m; ++i)
31         {
32             scanf("%d", &a[i]);
33         }
34         sort(a, a + m);
35         ans = (double)w / 3 / n;
36         ans = min(ans, (double)a[0]);
37         ans = min(ans, (double)a[n] / 2);
38         printf("%lf", ans*3*n);
39     }
40     return 0;
41 }
View Code

 

C题

给我们n,表示有n条桌腿,

然后接下来n个数字,Li表示桌腿的长度,

再接下来n个数组,di表示砍掉第i的桌腿的费用。

一个桌子要是稳定的,要求桌子最长的桌腿的条数占总条数的一半以上

问使得桌子稳定的最小花费

思路:将桌腿按长度排序,然后遍历桌腿,枚举桌腿的长度x作为最长的桌腿,那么比x长的桌腿应该去掉,

比x长的桌腿都排在x后面,所以我们可以维护一个后缀和,使得可以在O(1)的时间内获得砍掉比x长的所有桌腿的费用

设长度为x的桌腿有cnt条,那么要将比x短的桌腿砍掉剩下cnt-1条即可。 砍的时候,肯定是先砍费用小的。

比赛时的想法是用优先队列维护一个费用队列,队头的费用最小。但是时间复杂度超了(不去算算法的时间复杂度果然是不好的习惯)

其实费用的取值是1-->200,所以只要用个标记数组来标记,每次只要遍历标记数组就可以了。

技术分享
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <string>
 12 #include <math.h>
 13 #include <functional>
 14 using namespace std;
 15 #pragma warning(disable:4996)
 16 typedef long long LL;                   
 17 const int INF = 1<<30;
 18 /*
 19 
 20 */
 21 const int N = 100000 + 10;
 22 struct Node
 23 {
 24     int l, d;
 25     bool operator<(const Node&rhs)const
 26     {
 27         return l < rhs.l;
 28     }
 29 }a[N];
 30 int suffix[N],c[N];
 31 void input(int &x)
 32 {
 33     char ch = getchar();
 34     while (ch < 0 || ch>9)
 35         ch = getchar();
 36     x = 0;
 37     while (ch >= 0 && ch <= 9)
 38     {
 39         x = x * 10 + ch - 0;
 40         ch = getchar();
 41     }
 42 }
 43 int main()
 44 {
 45     int n, i, j, ans, k, total;
 46     while (scanf("%d", &n)!=EOF)
 47     {
 48         total = 0;
 49         for (i = 0; i < n; ++i)
 50             input(a[i].l);
 51         for ( i = 0; i < n; ++i)
 52             input(a[i].d);
 53             
 54         sort(a, a + n);
 55         for (i = 0; i < n; ++i)
 56              suffix[i] = a[i].d;
 57         for (i = n - 2; i >= 0; --i)
 58             suffix[i] += suffix[i + 1];
 59         i = 0;
 60         ans = INF;
 61         while (i < n)
 62         {
 63             int tmp = a[i].l;
 64             j = i;
 65             while (i < n && a[i].l == tmp)
 66                 i++;
 67             int cnt = i - j;
 68             tmp = 0;
 69             //砍掉比x更长的桌腿
 70             if (i<n)
 71                 tmp = suffix[i];
 72             //total统计的是比x短的桌腿条数
 73             int t = total;
 74             
 75             for (k = 1; k <= 200; ++k)
 76             {
 77                 if (t < cnt)
 78                     break;
 79                 if (t - c[k] >= cnt - 1)
 80                 {
 81                     tmp += c[k] * k;
 82                     t -= c[k];
 83                 }
 84                 else 
 85                 {
 86                     tmp += k * (t - cnt + 1);
 87                     break;
 88                 }
 89             }
 90             
 91             for (k = j; k < i; ++k)
 92             {
 93                 c[a[k].d]++;
 94                 total++;
 95             }
 96             ans = min(ans, tmp);
 97         }
 98         printf("%d\n", ans);
 99     }
100     return 0;
101 }
View Code

 

codeforece Round#311

标签:

原文地址:http://www.cnblogs.com/justPassBy/p/4612395.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!