标签:维护 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 }
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 }
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 }
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 }
标签:维护 one 实现 ret splay ems char 复杂 分享
原文地址:https://www.cnblogs.com/wyboooo/p/9744762.html