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

Codeforces Round #513-ABCD

时间:2018-10-05 16:09:14      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:维护   one   实现   ret   splay   ems   char   复杂   分享   

ABC现场做出,涨了八十几分吧。D有点思路不知道怎么实现,赛后看题解发现巨简单,想得太复杂了。蓝瘦。

 

A----http://codeforces.com/contest/1060/problem/A

题意:给定n位数,问能组成多少电话号码。电话号码是一个以8位开头的11位数

思路:统计一下8的个数,计算一下n/11的个数,两者取较小值即为答案

技术分享图片
 1 #include <bits/stdc++.h>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stdio.h>
 6 #include<cstring>
 7 #include<map>
 8 
 9 #define inf 0x3f3f3f3f
10 using namespace std;
11 typedef long long int LL;
12 
13 int n;
14 const int maxn = 105;
15 int dig[10];
16 
17 int main()
18 {
19     while(scanf("%d", &n) != EOF){
20         char str[maxn];
21         scanf("%s", str);
22         memset(dig, 0, sizeof(dig));
23         int cnt = 0;
24         for(int i = 0; i < n; i++){
25             dig[str[i] - 0]++;
26             cnt++;
27         }
28 
29         int ans = min(dig[8], cnt / 11);
30         cout<<ans<<endl;
31     }
32     return 0;
33 }
View Code

 

B---http://codeforces.com/contest/1060/problem/B

题意:给定一个n,要求两个数 a+b=n并且a的各数位之和和b的各数位之和相加是最大的,输出这个和

思路:有一个数一定是比n少一位的,全由9构成的数。

技术分享图片
 1 #include <bits/stdc++.h>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stdio.h>
 6 #include<cstring>
 7 #include<map>
 8 
 9 #define inf 0x3f3f3f3f
10 using namespace std;
11 typedef long long int LL;
12 
13 LL n;
14 
15 int main()
16 {
17     while(scanf("%I64d", &n) != EOF){
18         int dig = 0;
19         LL tmp = n;
20         while(tmp){
21             tmp /= 10;
22             dig++;
23         }
24 
25         dig--;
26         int ans = dig * 9;
27         tmp = n;
28         LL ten = 1;
29         while(dig){
30             tmp -= ten * 9;
31             ten *= 10;
32             dig--;
33         }
34         while(tmp){
35             ans += tmp % 10;
36             tmp /=10;
37         }
38         printf("%d\n", ans);
39     }
40     return 0;
41 }
View Code

 

C---http://codeforces.com/contest/1060/problem/C

题意:给定两个数组a和b,矩阵c(i,j) = ai * bj,求矩阵c的一个子矩阵使得子矩阵中所有元素和小于x,并且要让这个子矩阵的元素个数尽可能多

思路:c是不需要算出来的。找c的一个子矩阵相当于分别找a和b中连续的一段区间。

首先预处理出a和b中,连续的长度为i的区间之和最小的。asum[i]即为a数组中,连续的长度为i的总和最小的区间

因为要让元素个数尽可能多,那么就应该要找和最小值

然后分别枚举子矩阵的行数和列数,找到和小于x且元素个数最多的

技术分享图片
 1 #include <bits/stdc++.h>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stdio.h>
 6 #include<cstring>
 7 #include<map>
 8 
 9 #define inf 0x3f3f3f3f
10 using namespace std;
11 typedef long long int LL;
12 
13 int n, m;
14 const int maxn = 2005;
15 LL a[maxn], b[maxn], x;
16 LL suma[maxn], sumb[maxn];
17 LL asum[maxn], bsum[maxn];
18 
19 int main()
20 {
21     while(scanf("%d%d", &n, &m) != EOF){
22         memset(suma, 0, sizeof(suma));
23         memset(sumb, 0, sizeof(sumb));
24         for(int i = 1; i <= n; i++){
25             scanf("%I64d", &a[i]);
26             suma[i] = suma[i - 1] + a[i];
27         }
28         for(int i = 1; i <= m; i++){
29             scanf("%I64d", &b[i]);
30             sumb[i] = sumb[i - 1] + b[i];
31         }
32         scanf("%I64d", &x);
33 
34         memset(asum, inf, sizeof(asum));
35         memset(bsum, inf, sizeof(bsum));
36         for(int i = 1; i <= n; i++){
37             for(int pos = i; pos <= n; pos++){
38                 asum[i] = min(suma[pos] - suma[pos - i], asum[i]);
39             }
40         }
41         for(int i = 1; i <= m; i++){
42             for(int pos = i; pos <= m; pos++){
43                 bsum[i] = min(sumb[pos] - sumb[pos - i], bsum[i]);
44             }
45         }
46 
47         LL ans = 0;
48         for(int i = n; i >= 1; i--){
49             for(int j = m; j >= 1; j--){
50                 if(bsum[j] * asum[i] <= x){
51                     if(i * j > ans){
52                         ans = i * j;
53                     }
54                 }
55             }
56         }
57 
58         printf("%I64d\n", ans);
59     }
60     return 0;
61 }
View Code

 

D---http://codeforces.com/contest/1060/problem/D

题意:有n个人坐成一圈 每个人都要求他的左边至少有a[i]个空位,右边有b[i]个空位。问要满足所有人的要求至少需要多少凳子。

思路:

现场的思路是所有人和空位之和。每次都找到左边空位最大的那个人,和右边空位最大的那个进行合并,总数就减去。合并之后相当于形成一个新的人。但是一时想不出来我形成新的人之后要怎么继续维护,难道每次都排序,肯定是不够的。

其实,合并并没有影响左边的数组和右边的数组。合并之后的左边和右边原来就在数组之中。

所以只需要先对a和b数组分别排序,每次取出a和b中的最大值。答案加上这两个最大之中的较大。最后答案加上n就行了。

技术分享图片
 1 #include <bits/stdc++.h>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stdio.h>
 6 #include<cstring>
 7 #include<map>
 8 
 9 #define inf 0x3f3f3f3f
10 using namespace std;
11 typedef long long LL;
12 
13 int n;
14 const int maxn = 1e5 + 5;
15 int a[maxn], b[maxn];
16 
17 int main()
18 {
19     while(scanf("%d", &n) != EOF){
20         for(int i = 0; i < n; i++){
21             scanf("%d%d", &a[i], &b[i]);
22         }
23         sort(a, a + n);
24         sort(b, b + n);
25 
26         LL ans = n;
27         for(int i = 0; i < n; i++){
28             ans += max(a[i], b[i]);
29         }
30         printf("%I64d\n", ans);
31     }
32     return 0;
33 }
View Code

 

Codeforces Round #513-ABCD

标签:维护   one   实现   ret   splay   ems   char   复杂   分享   

原文地址:https://www.cnblogs.com/wyboooo/p/9744762.html

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