cychester

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\n", 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\n", 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\n", 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\n", cur0[i], cur0[i + 1]);
 44         rest--;
 45     }
 46     if(tot % 2 == 0 && cur0.size() && rest) {
 47         printf("2 %d\n", 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\n", 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\n", cur0[(int)cur0.size() - 1], pos);
 62         rest--;
 63         vis[cur0[(int)cur0.size() - 1]] = 1;
 64         if(rest) {
 65             printf("2 %d\n", 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\n", cur0[i], cur0[i + 1]);
 74             rest--;
 75         }
 76         if(rest) {
 77             printf("2 %d\n", 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\n", 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\n", 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\n", ans);
62 }
D. Petya and Array

 

posted on 2018-09-17 19:52  cychester  阅读(257)  评论(0编辑  收藏  举报

导航