zoukankan      html  css  js  c++  java
  • codeforces round#510

    蒟蒻和以前一样还是只能做 $4$ 题, 希望有一天可以 水到 $5$ 题!!
    不过也终于上了蓝了。。。
     

    A. Benches

    Description

    给出$N$个座位, 每个座位上初始有$a_i$ 个人, 这些人都不能移动。

    另外还有$M$个人, 要求让他们坐到座位上, $max$ 为所有座位上人数最多 的 人数。

    求出 $max$ 的可能最大值和 最小值。

    Solution

    最大值就是 给出的最多的人数 的座位 加上 $M$

    最小值可以二分答案, 容易求出

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define rd read()
     5 using namespace std;
     6 
     7 const int N = 1e3;
     8 
     9 int n, m, a[N], maxn;
    10 
    11 int read() {
    12     int X = 0, p = 1; char c = getchar();
    13     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
    14     for(;c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
    15     return X * p;
    16 }
    17 
    18 bool jud(int minn) {
    19     int rest = m;
    20     for(int i = 1; i <= n; ++i) {
    21         if(a[i] > minn) return false;
    22         rest -= minn - a[i];
    23     }
    24     if(rest > 0) return false;
    25     else return true;
    26 }
    27 
    28 int main()
    29 {
    30     n = rd; m = rd;
    31     for(int i = 1; i <= n; ++i)
    32         a[i] = rd;
    33     for(int i = 1; i <= n; ++i)
    34         maxn = max(maxn, a[i]);
    35     int l = 0, r = 2e4 + 5, ans = 0;
    36     while(l <= r) {
    37         int mid = (l + r) >> 1;
    38         if(jud(mid)) r = mid - 1, ans = mid;
    39         else l = mid + 1;
    40     }
    41     printf("%d %d
    ", ans, maxn + m);
    42 }
    A. Benches

    B. Vitamins

    Description

    给出$N$种维生素药, 第$a_i$种药包含了$A,B,C,$中的其中一种或多种维生素, 每一种药都有其价格$cost_i$

    现要求出 能吃到维生素 $A,B,C$ 至少花费多少钱。

    Solution

    显然, 药最多只有7种, 用$2$进制 $S$ 表示是否含有某种维生素, 该种药的最小价格记为 $minn[S]$

    在输入时,我们把第 $i$ 种药 更新到对应的 含有维生素的集合S。

    求最后的答案时, 只需要三种枚举就行了:

    $1$ : 买一种药, 对应集合 $111(B)$

    $2$ : 买两种药 $i$ 和 $j$, 并且$i | j = 111(B)$

    $3$: 买三种药 $i$ 和 $j$, 并且$i | j | k = 111(B)$

    求其中的最小值即可。

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 const int N = 1e3 + 5;
     7 const int inf = ~0U >> 4;
     8 
     9 int n, v[10], minn[10], ans = inf;
    10 
    11 char s[10];
    12 
    13 struct node {
    14     int cost, vis;
    15 }a[N];
    16 
    17 int main()
    18 {
    19     for(int i = 0; i < 10; ++i)
    20         minn[i] = inf;
    21     scanf("%d", &n);
    22     for(int i = 1; i <= n; ++i) {
    23         memset(s, 0,sizeof(s));
    24         memset(v, 0, sizeof(v));
    25         scanf("%d%s", &a[i].cost, s);
    26         for(int j = 0, len = strlen(s); j < len; ++j)
    27             a[i].vis |= 1 << (s[j] - 'a');
    28         minn[a[i].vis] = min(minn[a[i].vis], a[i].cost);
    29     }
    30     ans = min(ans, minn[7]);
    31     for(int i = 1; i < 8; ++i)
    32         for(int j = 1; j < 8; ++j)
    33             if((i | j) == 7) ans = min(ans, minn[i] + minn[j]);
    34     for(int i = 1; i < 8; ++i)
    35         for(int j = 1; j < 8; ++j)
    36             for(int k = 1; k < 8; ++k)
    37                 if((i | j | k) == 7)
    38                     ans = min(ans, minn[i] + minn[j] + minn[k]);
    39     printf("%d
    ", ans == inf ? -1 : ans);
    40 }
    B. Vitamins

    C. Array Product

    Description

    给出一个有$N$项的序列${a}$, 有两种操作

    $1$: 选择两个数 $i$  $j$, 把$j$ 位置上的数更新为$a_j * a_i$, 将$i$ 位置上的数删去(删去后不能再进行操作)

    $2$: 选择一个数$i$, 将 $i$ 位置上的数直接删去 ( 该种操作最多只能进行$1$次)

    问如何操作才能使 $N-1$ 次操作后剩下的那个数最大, 输出操作的方案。

    Solution 

    大佬说这是前四题最不可做的, 所以我 先水了D题, 最后还WA了两次才 在1:52的时候过(好像我rank并没有升多少

    有如下4中情况:

    $1$ : 序列中有 奇数个 负数, 并且 存在 $0$—— 将所有的 $0$ 合并成一个,再把 $0$ 和 绝对值最小的 负数 合并 得到 $0$, 删去这个 $0$ 后 把剩余的数合并。

    $2$ : 序列中有 奇数个 负数, 并且 不存在 $0$—— 直接删除 绝对值最小的负数, 剩下的合并。

    $3$ : 序列中有 偶数个 负数, 并且存在 $0$—— 把所有的$0$ 合并成一个, 把 $0$ 删去, 剩下的数合并

    $4$ : 序列中有 偶数个负数, 并且 不存在 $0$—— 直接合并。

    Code

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #define rd read()
      6 using namespace std;
      7 
      8 const int N = 2e5 + 5;
      9 const int inf = ~0U >> 1;
     10 
     11 int a[N], vis[N], tot, n, rest;
     12 
     13 vector<int> cur0, cur1;
     14 
     15 int read() {
     16     int X = 0, p = 1; char c = getchar();
     17     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
     18     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
     19     return X * p;
     20 }
     21 
     22 int main()
     23 {
     24     n = rd;
     25     rest = n - 1;
     26     a[0] = -inf;
     27     for(int i = 1; i <= n; ++i) {
     28         a[i] = rd;
     29         if(a[i] < 0) tot++;
     30         if(a[i] < 0) cur1.push_back(i);
     31         if(a[i] == 0) cur0.push_back(i);
     32     }
     33     /*if((tot & 1)) {
     34         int pos = 0;
     35         for(int i = 0, len = cur1.size(); i < len; ++i)
     36             if(a[pos] < a[cur1[i]]) pos = cur1[i];
     37         vis[pos] = 1;
     38         printf("2 %d
    ", pos);
     39         rest--;
     40     }
     41     for(int i = 0, len = cur0.size(); i < len - 1 && rest; ++i) {
     42         vis[cur0[i]] = 1;
     43         printf("1 %d %d
    ", cur0[i], cur0[i + 1]);
     44         rest--;
     45     }
     46     if(tot % 2 == 0 && cur0.size() && rest) {
     47         printf("2 %d
    ", cur0[(int)cur0.size() - 1]);
     48         vis[cur0[(int)cur0.size() - 1]] = 1;
     49         rest --;
     50     }*/
     51 
     52     if(tot % 2 && cur0.size()) {
     53         for(int i = 0, len = cur0.size(); i < len - 1 && rest; ++i) {
     54             vis[cur0[i]] = 1;
     55             printf("1 %d %d
    ", cur0[i], cur0[i + 1]);
     56             rest--;
     57         }
     58         int pos = 0;
     59         for(int i = 0, len = cur1.size(); i < len; ++i)
     60             if(a[pos] < a[cur1[i]]) pos = cur1[i];
     61         printf("1 %d %d
    ", cur0[(int)cur0.size() - 1], pos);
     62         rest--;
     63         vis[cur0[(int)cur0.size() - 1]] = 1;
     64         if(rest) {
     65             printf("2 %d
    ", pos);
     66             vis[pos] = 1;
     67             rest--;
     68         }
     69     }
     70     else if(cur0.size()) {
     71         for(int i = 0, len = cur0.size(); i < len - 1 && rest; ++i) {
     72             vis[cur0[i]] = 1;
     73             printf("1 %d %d
    ", cur0[i], cur0[i + 1]);
     74             rest--;
     75         }
     76         if(rest) {
     77             printf("2 %d
    ", cur0[(int)cur0.size() - 1]);
     78             vis[cur0[(int)cur0.size() - 1]] = 1;
     79             rest --;
     80 
     81         }    
     82     }
     83     else if(!cur0.size() && tot % 2) {
     84         int pos = 0;
     85         for(int i = 0, len = cur1.size(); i < len; ++i)
     86             if(a[pos] < a[cur1[i]]) pos = cur1[i];
     87         printf("2 %d
    ", pos);
     88         rest--;
     89         vis[pos] = 1;
     90     }
     91     for(int i = 1, j = 1; rest;) {
     92         while(vis[i] && i <= n) i++;
     93         j = i + 1;
     94         while(vis[j] && j <= n) j++;
     95         printf("1 %d %d
    ", i, j);
     96         vis[i] = 1;
     97         rest--;
     98     }
     99     
    100 }
    C. Array Product

    D. Petya and Array

    Description

    求出有多少个 子段的 和 $<t$

    Solution

    跟树状数组求逆序对一样的原理。

    我不会用语言表述 $QuQ$ (╥╯^╰╥)

    简单说, 就是先求出前缀和$sum$, 当前我们需要求出以$i$ 为结尾的子段有多少个满足$sum[i] - sum[j] < t$,$0<=j<i$

    这样而树状数组求静态逆序对就相当于 $t = 0$时的做法了。

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define rd read()
     5 #define ll long long
     6 using namespace std;
     7 
     8 const int N = 2e5 + 5;
     9 
    10 int n, a[N];
    11 ll qsum[N], t, b[N], tot;
    12 ll sum[N], ans;
    13 
    14 ll read() {
    15     ll X = 0, p = 1; char c = getchar();
    16     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
    17     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
    18     return X * p;
    19 }
    20 
    21 int fd(ll x) {
    22     int tmp =  lower_bound(b + 1, b + 1 + tot, x) - b;
    23     if(b[tmp] == x) return tmp;
    24     else return tmp - 1;
    25 }
    26 
    27 int lowbit(int x) {
    28     return x & -x;
    29 }
    30 
    31 ll query(int x) {
    32     ll re = 0;
    33     for(; x; x -= lowbit(x)) re += sum[x];
    34     return re;
    35 }
    36 
    37 void add(int x) {
    38     for(; x <= tot; x += lowbit(x))
    39         sum[x]++;
    40 }
    41 
    42 int main()
    43 {
    44     n = rd; t = rd;
    45     for(int i = 1; i <= n; ++i)
    46         a[i] = rd;
    47     for(int i = 1; i <= n; ++i) {
    48         qsum[i] = qsum[i - 1] + a[i];
    49         b[++tot] = qsum[i];
    50     }
    51     b[++tot] = 0;
    52     sort(b + 1, b + 1 + tot);
    53     tot = unique(b + 1, b + 1 + tot) - b - 1;
    54     add(fd(0));
    55     for(int i = 1; i <= n; ++i) {
    56         int tmp = fd(qsum[i] - t);
    57         ans += (i - query(tmp));
    58         tmp = fd(qsum[i]);
    59         add(tmp);
    60     }
    61     printf("%I64d
    ", ans);
    62 }
    D. Petya and Array
  • 相关阅读:
    ibatis 循环迭代
    javascript 中Table、TableCell 、TableRow对象
    Java重载Java构造器
    java垃圾回收机制
    Java在J2EE工程中路径寻址问题终极解决方案
    JAVASCRIPT 验证计算中英文混合字符串长度的解决
    java基础学习及总结
    ORACLE nvarchar2和varchar2的区别
    StringBuffer的用法
    关于Ant下的路径查找
  • 原文地址:https://www.cnblogs.com/cychester/p/9664457.html
Copyright © 2011-2022 走看看