zoukankan      html  css  js  c++  java
  • codeforece Round#311 BCDE

    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
    ", 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
    ", ans);
     99     }
    100     return 0;
    101 }
    View Code

    D题:

    给定一个图,问最少要加多少条边才使得图有长度为奇数的环。并输出方案数。

    第一种情况:如有m=0,那么考虑一个环最少有3个点,3条边,所以我们要从n个点中选3个点,并且加上3条边就可以形成环

    方案书是C(n,3)

    第二种情况:每个点的度数不超过1(即图的最大连通分量只有2个点),那么只要加2条边,且方案数为   2个点的连通分量加独立的点形成的方案数(n-2*m)*n  

    + 2个点的连通分量加2个点的连通分量所形成环的方案书 2*m(m-1)

    第三种情况:那么肯定最大连通分量有3个点,那么只要加1条边就可以了。所以只要将图染色,将黑色的点,或者白色的点连起来就形成环了

    方案数是所有连通分量的 C(黑色,2) + C(白色,2)

    当然了,如果图本身就存在奇数环, 那么输出0 1 就好了

     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 /*
    18 
    19 */
    20 const int N = 1000000 + 10;
    21 vector<int> g[N];
    22 int d[N];
    23 int color[N];
    24 bool hasOddCycle;
    25 void dfs(int u, int fa,int &cnt, int &black)
    26 {
    27     
    28     for (int i = 0; i < g[u].size(); ++i)
    29     {
    30         int v = g[u][i];
    31         if (v == fa) continue;
    32         if (color[v] == -1)
    33         {
    34             color[v] = color[u] ^ 1;
    35             black += color[v];
    36             cnt += 1;
    37             dfs(v, u, cnt, black);
    38         }
    39         else if (color[u] == color[v])
    40         {
    41             hasOddCycle = true;
    42         }
    43         
    44     }
    45 }
    46 int main()
    47 {
    48     int n, m, a, b;
    49     bool flag = false;
    50     scanf("%d%d", &n, &m);
    51     if (m == 0)
    52     {
    53         printf("%d %I64d
    ", 3, (LL)n*(n - 1)*(n-2) / 6);
    54         return 0;
    55     }
    56     for (int i = 0; i < m; ++i)
    57     {
    58         scanf("%d%d", &a, &b);
    59         g[a].push_back(b);
    60         g[b].push_back(a);
    61         d[a]++;
    62         d[b]++;
    63         if (d[a]>1 || d[b] > 1)
    64             flag = true;
    65     }
    66     if (!flag)
    67     {
    68         printf("%d %I64d
    ", 2, (LL)(n - 2 * m)*m + (LL)2 * m*(m - 1));
    69         return 0;
    70     }
    71     memset(color, -1, sizeof(color));
    72     LL ans = 0;
    73     int cnt, black;
    74     for (int i = 1; i <= n; ++i)
    75     {
    76         if (color[i] == -1)
    77         {
    78             cnt = black = 1;
    79             color[i] = 1;
    80             dfs(i, -1, cnt, black);
    81             ans += (LL)black*(black - 1) / 2 + (LL)(cnt - black)*(cnt - black - 1) / 2;
    82         }
    83         if (hasOddCycle)
    84             break;
    85     }
    86     if (hasOddCycle)
    87         printf("%d %d
    ", 0, 1);
    88     else
    89         printf("%d %I64d
    ", 1, ans);
    90 
    91     return 0;
    92 }
    View Code

    E题

    用dp的方法在O(n*n)的时间内求出所有的half-palindrome. 然后将所有的子串都插入字典树中,时间复杂度同样是O(n*n),然后dfs到第k个half-palindrome

    dfs的时间复杂度同样是O(n*n),因为字典树的节点数不超过O(n*n)

     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 /*2
    18 
    19 */
    20 int root, size, k, m = -1;
    21 const int N = 5000 + 10;
    22 bool ok[N][N];
    23 char str[N], ans[N];
    24 struct Trie
    25 {
    26     int cnt, next[2];
    27     void init()
    28     {
    29         cnt = 0;
    30         next[0] = next[1] = -1;
    31     }
    32 }trie[N*N];
    33 
    34 void add(int i, int n)
    35 {
    36     int cur = root;
    37     for (int j = i; j < n; ++j)
    38     {
    39         if (trie[cur].next[str[j] - 'a'] == -1)
    40         {
    41             trie[size].init();
    42             trie[cur].next[str[j] - 'a'] = size++;
    43         }
    44         cur = trie[cur].next[str[j] - 'a'];
    45         if (ok[i][j])
    46             trie[cur].cnt++;
    47     }
    48 }
    49 void dfs(int cur)
    50 {
    51     k -= trie[cur].cnt;
    52     if (k <= 0)
    53     {
    54         printf("%s
    ", ans);
    55         exit(0);
    56     }
    57     for (int i = 0; i < 2; ++i)
    58     {
    59         if (trie[cur].next[i] != -1)
    60         {
    61             ans[++m] = 'a' + i;
    62             dfs(trie[cur].next[i]);
    63             ans[m--] = 0;
    64         }
    65     }
    66 }
    67 int main()
    68 {
    69     scanf("%s%d", str,&k);
    70     int n = strlen(str);
    71     size = 1;
    72     trie[root].init();
    73     for (int len = 1; len <= n; ++len)
    74     {
    75         for (int i = 0; i <= n - len; ++i)
    76         {
    77             int j = i + len - 1;
    78             if (j - i <= 3)
    79                 ok[i][j] = str[i] == str[j];
    80             else
    81                 ok[i][j] = str[i] == str[j] && ok[i + 2][j - 2];
    82         }
    83     }
    84     for (int i = 0; i < n; ++i)
    85         add(i, n);
    86     dfs(root);
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    密码由6-12位数字或字母组成,密码哈希加密
    获得一个字符串的汉语拼音码
    WPF中ComboBox绑定数据库自动读取产生数据
    SQL存储过程生成顺序编码
    SQL 语句调用这个存储过程,生成顺序编码
    restful(1):序列化
    Django的CBV和FBV
    权限管理组件:rbac
    ModelForm组件和forms组件补充
    BBS+Blog项目代码
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4612395.html
Copyright © 2011-2022 走看看