Educational Codeforces Round 19

  由于时间原因只A掉了前三题。

Problem#A k-Factorization

  题目传送门[here]

  题目大意是说给出一个数n,能不能把它分成k个严格大于1的整数的乘积,如果可以,随便输出一种方案,否则就输出-1。

  首先对n进行质因数分解,如果质因数的个数小于k就输出-1,否则随便合并几个使总数为k,然后输出就好了。

Code

 1 /**
 2  * CodeForces
 3  * Problem#797A
 4  * Accepted
 5  * Time:15ms
 6  * Memory:2044k
 7  */
 8 #include<iostream>
 9 #include<fstream>
10 #include<sstream>
11 #include<algorithm>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<cctype>
16 #include<cmath>
17 #include<ctime>
18 #include<map>
19 #include<stack>
20 #include<set>
21 #include<queue>
22 #include<vector>
23 using namespace std;
24 typedef bool boolean;
25 #define inf 0xfffffff
26 #define smin(a, b) (a) = min((a), (b))
27 #define smax(a, b) (a) = max((a), (b))
28 template<typename T>
29 inline boolean readInteger(T& u) {
30     char x;
31     int aFlag = 1;
32     while(!isdigit((x = getchar())) && x != ‘-‘ && x != -1);
33     if(x == -1)    {
34         ungetc(x, stdin);
35         return false;
36     }
37     if(x == ‘-‘) {
38         aFlag = -1;
39         x = getchar();
40     }
41     for(u = x - ‘0‘; isdigit((x = getchar())); u = u * 10 + x - ‘0‘);
42     u *= aFlag;
43     ungetc(x, stdin);
44     return true;
45 }
46
47 int n, k;
48 int top = 0;
49 int a[40];
50
51 inline void init() {
52     readInteger(n);
53     readInteger(k);
54 }
55
56 inline void solve() {
57     int m = (int)sqrt(n + 0.5);
58     for(int i = 2; i <= m && n > 1; i++) {
59         while(n % i == 0) a[top++] = i, n /= i;
60     }
61     if(n != 1)    a[top++] = n;
62     if(top < k)    printf("-1");
63     else {
64         int s = 1;
65         for(int i = 0; i <= top - k; i++)
66             s *= a[i];
67         if(s > 1)    printf("%d ", s);
68         for(int i = top - k + 1; i < top; i++)
69             printf("%d ", a[i]);
70     }
71 }
72
73 int main() {
74     init();
75     solve();
76     return 0;
77 }

Problem#A

Problem#B Odd sum

  题目传送门[here]

  题目大意是说给定一个序列,找到一个子序列,使它的和为奇数,求这个最大的和。

  记录一个最大的偶数和和奇数和,然后更新就好了。

Code

 1 /**
 2  * CodeForces
 3  * Problem#797B
 4  * Accepted
 5  * Time:30ms
 6  * Memory:2432k
 7  */
 8 #include<iostream>
 9 #include<fstream>
10 #include<sstream>
11 #include<algorithm>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<cctype>
16 #include<cmath>
17 #include<ctime>
18 #include<map>
19 #include<stack>
20 #include<set>
21 #include<queue>
22 #include<vector>
23 using namespace std;
24 typedef bool boolean;
25 #define inf 0xfffffff
26 #define smin(a, b) (a) = min((a), (b))
27 #define smax(a, b) (a) = max((a), (b))
28 template<typename T>
29 inline boolean readInteger(T& u) {
30     char x;
31     int aFlag = 1;
32     while(!isdigit((x = getchar())) && x != ‘-‘ && x != -1);
33     if(x == -1)    {
34         ungetc(x, stdin);
35         return false;
36     }
37     if(x == ‘-‘) {
38         aFlag = -1;
39         x = getchar();
40     }
41     for(u = x - ‘0‘; isdigit((x = getchar())); u = u * 10 + x - ‘0‘);
42     u *= aFlag;
43     ungetc(x, stdin);
44     return true;
45 }
46
47 int n;
48 int* a;
49 int modd = -2e9, muodd = 0;
50
51 inline void init() {
52     readInteger(n);
53     a = new int[(const int)(n + 1)];
54     for(int i = 1; i <= n; i++)
55         readInteger(a[i]);
56 }
57
58 inline void solve() {
59     for(int i = 1; i <= n; i++) {
60         int x0 = a[i] + muodd, x1 = a[i] + modd;
61         if(x0 & 1)    smax(modd, x0);
62         else smax(muodd, x0);
63         if(x1 & 1)    smax(modd, x1);
64         else smax(muodd, x1);
65     }
66     printf("%d", modd);
67 }
68
69 int main() {
70     init();
71     solve();
72     return 0;
73 }

Problem#B

Problem#C Minimal string

  题目传送门[here]

  题目大意是说给定一个字符串,用一个栈对它进行"排序",使得排序后的字符串字典序最小。

  这是一道贪心题,如果说栈顶的字符所在原字符串的位置的右边的最小值比它小,就一直往右把字符加进栈,直到某个位置不存在,就把它弹出栈。由于原字符串经过各种抽取使得它残缺不全,所以不能直接记录最小值,用了一个线段树来维护,每将一个字符弹出栈就在线段树中把它所在的位置的值修改得很大很大。因为每个字符只会进栈出栈一次,所以总时间复杂度为O(nlog2n)

Code

  1 /**
  2  * CodeForces
  3  * Problem#797C
  4  * Accepted
  5  * Time:46ms
  6  * Memory:7360k
  7  */
  8 #include<iostream>
  9 #include<fstream>
 10 #include<sstream>
 11 #include<algorithm>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<cctype>
 16 #include<cmath>
 17 #include<ctime>
 18 #include<map>
 19 #include<stack>
 20 #include<set>
 21 #include<queue>
 22 #include<vector>
 23 using namespace std;
 24 typedef bool boolean;
 25 #define inf 0xfffffff
 26 #define smin(a, b) (a) = min((a), (b))
 27 #define smax(a, b) (a) = max((a), (b))
 28
 29 typedef class SegTreeNode {
 30     public:
 31         char val;
 32         SegTreeNode *l, *r;
 33         SegTreeNode():val(127), l(NULL), r(NULL) {        }
 34
 35         inline void pushUp() {
 36             val = min(l->val, r->val);
 37         }
 38 }SegTreeNode;
 39
 40 typedef class SegTree {
 41     public:
 42         SegTreeNode* root;
 43
 44         SegTree():root(NULL) {    }
 45         SegTree(int n, char* s) {
 46             build(root, 1, n, s);
 47         }
 48
 49         void build(SegTreeNode*& node, int l, int r, char* s) {
 50             node = new SegTreeNode();
 51             if(l == r) {
 52                 node->val = s[l];
 53                 return;
 54             }
 55             int mid = (l + r) >> 1;
 56             build(node->l, l, mid, s);
 57             build(node->r, mid + 1, r, s);
 58             node->pushUp();
 59         }
 60
 61         void update(SegTreeNode*& node, int l, int r, int idx, char val) {
 62             if(l == idx && r == idx) {
 63                 node->val = val;
 64                 return;
 65             }
 66             int mid = (l + r) >> 1;
 67             if(idx <= mid)    update(node->l, l, mid, idx, val);
 68             else update(node->r, mid + 1, r, idx, val);
 69             node->pushUp();
 70         }
 71
 72         char query(SegTreeNode*& node, int l, int r, int ql, int qr) {
 73             if(l == ql && r == qr)
 74                 return node->val;
 75             int mid = (l + r) >> 1;
 76             if(qr <= mid)    return query(node->l, l, mid, ql, qr);
 77             else if(ql > mid)    return query(node->r, mid + 1, r, ql, qr);
 78             int a = query(node->l, l, mid, ql, mid);
 79             int b = query(node->r, mid + 1, r, mid + 1, qr);
 80             return min(a, b);
 81         }
 82 }SegTree;
 83
 84 int n;
 85 char s[100005];
 86 int top = 0;
 87 char* sta;
 88 int* idx;
 89 SegTree st;
 90
 91 inline void init() {
 92     scanf("%s", s + 1);
 93     n = strlen(s + 1);
 94     sta = new char[(const int)(n + 5)];
 95     idx = new int[(const int)(n + 5)];
 96     st = SegTree(n, s);
 97 }
 98
 99 inline void solve() {
100     int front = 1;
101     sta[0] = 127;
102     idx[0] = 0;
103     while(front <= n || top) {
104         if(front <= n) {
105             while(front <= n && sta[top] > st.query(st.root, 1, n, idx[top] + 1, n))
106                 sta[++top] = s[front], idx[top] = front++;
107             st.update(st.root, 1, n, idx[top], 127);
108             putchar(sta[top--]);
109         } else {
110             putchar(sta[top--]);
111         }
112     }
113 }
114
115 int main() {
116     init();
117     solve();
118     return 0;
119 }

Problem#C

  不过这道题似乎有更简单的实现方法,时间复杂度为O(nk),其中k为字符集大小,这里为26

时间: 2024-10-14 22:33:01

Educational Codeforces Round 19的相关文章

Educational Codeforces Round 19 B. Odd sum(贪心或dp)

题意:给出一组数,从中拿出几个,要让它们之和最大并且为奇数. 这道题给出的n不大,贪心暴力一下就可以了.(-?-;) 1.贪心 我是先把数据大于0并且为偶数的数都先加起来(保证开始的sum是偶数),数据大于0且为奇数的存在a数组里,数据小于0的存在b数组里. 然后如果有a数组有奇数个,直接加起来输出就好了.奇*奇=奇 偶数个的话就从sum中拿出a1,b1.特判一下a1(a数组里面最小的那个)和b1(b数组里最大的那个)哪个的绝对值大. a1<b1 直接输出之前的sum,a1>=b1则输出sum

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Educational Codeforces Round 26 D. Round Subset(dp)

题目链接:Educational Codeforces Round 26 D. Round Subset 题意: 给你n个数,让你选其中的k个数,使得这k个数的乘积的末尾的0的个数最大. 题解: 显然,末尾乘积0的个数和因子2和因子5的个数有关. 然后考虑dp[i][j]表示选i个数,当前因子5的个数为j时,能得到因子2最多的为多少. 那么对于每个数,记录一下因子2和5的个数,做一些01背包就行了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) me

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Educational Codeforces Round 23 D. Imbalanced Array(单调栈)

题目链接:Educational Codeforces Round 23 D. Imbalanced Array 题意: 给你n个数,定义一个区间的不平衡因子为该区间最大值-最小值. 然后问你这n个数所有的区间的不平衡因子和 题解: 对每一个数算贡献,a[i]的贡献为 当a[i]为最大值时的 a[i]*(i-l+1)*(r-i+1) - 当a[i]为最小值时的a[i]*(i-l+1)*(r-i+1). 计算a[i]的l和r时,用单调栈维护.具体看代码,模拟一下就知道了. 然后把所有的贡献加起来.

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu

Educational Codeforces Round 23 E. Choosing The Commander (trie)

题目链接: Educational Codeforces Round 23 E. Choosing The Commander 题意: 一共有n个操作. 1.  插入一个数p 2.  删除一个数p 3.  询问有多少个数 使得 x^p<l 题解: 对于前两种操作用01trie就能解决. 对于对三个操作,我们考虑在trie上搜索. 1.  当l的bit位是1时,那边bit位是p的字数全部的数都会小于l,(因为p^p=0) 2.  当l的bit为是0时,那边只能向bit位是p的子树中搜. 这样算下来

Educational Codeforces Round 22 E. Army Creation(主席树)

题目链接:Educational Codeforces Round 22 E. Army Creation 题意: 给你n个数和一个数k,然后有q个询问. 每个询问 有一个区间[l,r],问你这个区间内在满足每一种数不超过k的情况下,最大能选多少个数出来. 强制在线. 题解: 一看就要用到主席树,和主席数求区间内有多少不同的数的个数处理方法相同. 依次将每个数插入,当这个数出现的个数等于k了,就把最前面的那个数删掉. 然后询问就访问root[r]就行了. 第一次写完数据结构没有调试一遍过样例,一

Educational Codeforces Round 21 D. Array Division

题目链接:Educational Codeforces Round 21 D. Array Division 题意: 给你n个数,现在你可以改变1<=个数的位置,然后问你是否存在有一个k,使得sum(a[i])(1<=i<=k)==sum(a[j])(k+1<=j<=n) 题解: 分析: 如果需要将一个数移动,无非就是将这个数从第一部分移到第二部分,或者从第二部分移到第一部分. 所以,我们只需要开两个map来记录一下两部分有哪些数. 当两部分的差值/2等于其中一部分的一个数时