【解题报告】Codeforces Round #401 (Div. 2)
来源:互联网 发布:手机网络连接超时 编辑:程序博客网 时间:2024/06/07 08:02
题目链接
A. Shell Game(Codeforces 777A)
思路
为了更好地找到解题关键,先将小球随杯子运动的轨迹画在纸上。具体地,假设初始状态球在杯子
于是我们用二维数组
代码
#include <bits/stdc++.h>using namespace std;int n, x;int d[3][6] = { {0, 1, 2, 2, 1, 0}, {1, 0, 0, 1, 2, 2}, {2, 2, 1, 0, 0, 1} };int main() {// freopen("data.txt", "r", stdin); cin >> n >> x; n = n % 6; for(int i = 0; i < 3; i++) { if(d[i][n] == x) { cout << i << endl; break; } } return 0;}
B. Game of Credit Cards(Codeforces 777B)
思路
首先这个数据规模暴力肯定是不行了。那么潜在的,可能有贪心策略也可能是动态规划。那么先考察有没有贪心策略。因为两个字符串的序对本题是没有影响的(因为M已经知道S的出牌顺序)。因此考虑对两个字符串进行排序。我们分两种策略来考虑:
- 被
S 攻击的最少次数。假设我们是M ,那么我们的目标是让对方的牌尽可能不发挥作用。我们从当前S 的点数最大的S[i] 这儿考虑。为了让S[i] 哑火,我们可以拿出最大的M[j] 来压制它。这样为什么是最好的呢?因为如果M[j] 都压不住它,那么也没有牌能够压住它了。况且如果此时不用M[j] ,有什么理由以后再用它呢?有人可能会反驳:能不能放弃压制S[i] ,把M[j] 留到后面用呢?假如这样做,那么最好的情况是结果不变,最差的情况是结果变大了(也就是次优解)。因此我们按照点数从大到小枚举S[i] ,用当前最大的牌来压制对方即可。 - 攻击
S 的最多次数。假设我们是M ,那我们的目标是让我们的牌尽可能发挥作用。那么我们从M 的点数最大的M[j] 这儿考虑。为了让M[j] 发挥最大效果,我们选择比M[j] 小的(或相等的)最大的S[i] 下手。因为对于任意满足S[k]≤S[i] 的k ,都存在S[k]≤M[j] ,那么将M[j] 用在S[i] 上最利于我方的后来的牌的发挥。我们同样可以从大到小枚举S[j] ,用当前最大的牌来压制对方。
代码
#include <bits/stdc++.h>using namespace std;const int maxn = 1010;char S[maxn], M[maxn];int n, Max, Min;int main() {// freopen("data.txt", "r", stdin); scanf("%d%s%s", &n, S, M); sort(S, S + n); sort(M, M + n); int j = n - 1; for(int i = n - 1; i >= 0; i--) { if(S[i] > M[j]) { Min++; } else { j--; } } j = n - 1; for(int i = n - 1; i >= 0; i--) { if(S[i] < M[j]) { Max++; j--; } } printf("%d\n%d\n", Min, Max); return 0;}
C. Alyona and Spreadsheet(Codeforces 777C)
思路
对于这题,不少人都能够立即想到暴力的解法:对于每列
事实上,这种要对矩阵进行某种统计,暴力解复杂度太大的题,多半是要维护某种神奇的量,使得我们只用枚举行或枚举列就能完成这种统计。话说
那么这题怎么样呢?我们可以事先统计
对于第
不等式左边的式子表示以
是否存在一个
显然这个问题就是在问
那么对于每个
最后,实现上需要注意一个细节。因为题目只说
代码
#include <bits/stdc++.h>using namespace std;const int maxn = 1e5 + 10;vector <int> a[maxn], d[maxn];int n, m, k, l, r, num, Max[maxn];int main() {// freopen("data.txt", "r", stdin); scanf("%d%d", &n, &m); // 输入并存储矩阵 for(int i = 1; i <= n; i++) { a[i].push_back(0); for(int j = 1; j <= m; j++) { scanf("%d", &num); a[i].push_back(num); } } for(int j = 1; j <= m; j++) { d[j].push_back(0); d[j].push_back(1); } // 对每列计算以某个元素结尾的最长不下降子串 for(int j = 1; j <= m; j++) { for(int i = 2; i <= n; i++) { if(a[i][j] >= a[i-1][j]) { d[j].push_back(d[j][i-1] + 1); } else { d[j].push_back(1); } } } // 统计每行的列最长不下降子串的最大值 for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { Max[i] = max(Max[i], d[j][i]); } } // 回答查询 scanf("%d", &k); while(k--) { scanf("%d%d", &l, &r); puts(r - Max[r] + 1 <= l ? "Yes" : "No"); } return 0;}
D. Cloud of Hashtags(Codeforces 777D)
思路
这题从数据规模和“字典序”这个这么强的条件来看,可能存在贪心策略。首先从先往后考虑,结果是没什么结果。那么从后往前考虑呢?首先,对于一个字符串,我们删除它的后缀只会让它的字典序变小而不是变大。那么,对于倒数第一个串
从这个灵感不难得出贪心算法:我们从第一位开始逐位比较两个字符串
- 如果出现某位j使得
s[i][j]>s[i−1][j] ,那么一切顺利。 - 如果出现某位j使得
s[i][j]<s[i−1][j] ,那么从j 开始的s[i−1] 的后缀要全部删除掉。 - 如果一直是
s[i][j]==s[i−1][j] 直到某个串被遍历完,那么只需要s[i] 的长度大于或等于s[i−1] 的长度即可。
代码
#include <bits/stdc++.h>using namespace std;const int maxn = 5e5 + 10;string s[maxn];bool equ;int n, p1, p2;int main() {// freopen("data.txt", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); cin >> n; for(int i = 1; i <= n; i++) { cin >> s[i]; } for(int i = n - 1; i >= 1; i--) { equ = true; p1 = p2 = 0; while(true) { if(s[i+1][p1] < s[i][p2]) { if(true == equ) { s[i] = s[i].substr(0, p2); } break; } if(s[i+1][p1] > s[i][p2]) { equ = false; } if(++p2 >= s[i].size()) { break; } if(++p1 >= s[i+1].size()) { if(true == equ) { s[i] = s[i].substr(0, p2); } break; } } } for(int i = 1; i <= n; i++) { cout << s[i] << endl; } return 0;}
E. Hanoi Factory(Codeforces 777E)
思路
这题显然不是贪心能够解决的(很难找到某个顺序进行某种贪心策略)。考虑动态规划。我们需要有一个“序”来让动规满足“无后效性”。根据题目的特点先按照外径从大到小对
令状态
这看上去会是一个
代码
#include <bits/stdc++.h>using namespace std;#define lch (k << 1)#define rch (k << 1 | 1)#define mid ((l + r) >> 1)typedef long long ll;const int maxn = 2e5 + 10;map <int, int> mp;int n, a, b, h, m, foo[maxn], bar[maxn];ll d, tmp, ans;// 排序用的ring结构体struct ring { int a, b, h; ring() {} ring(int a, int b, int h):a(a), b(b), h(h) {} bool operator < (const ring& o) const { if(b == o.b) { return a > o.a; } return b > o.b; }}rings[maxn];// 线段树template <class T>struct Tree { T data[maxn<<2]; T operate(T x, T y) { return max(x, y); } void pushUp(int k) { data[k] = operate(data[lch], data[rch]); } // 建树 void build(int k, int l, int r) { if(l == r) { data[k] = 0; return; } build(lch, l, mid); build(rch, mid + 1, r); pushUp(k); } // 修改 void update(int a, T v, int k, int l, int r) { if(l == r) { data[k] = v; return; } if(a <= mid) { update(a, v, lch, l, mid); } else { update(a, v, rch, mid + 1, r); } pushUp(k); } // 查询 T query(int a, int b, int k, int l, int r) { if(a <= l && r <= b) { return data[k]; } ll res = 0; if(a <= mid) { res = operate(res, query(a, b, lch, l, mid)); } if(b > mid) { res = operate(res, query(a, b, rch, mid + 1, r)); } return res; }};Tree <ll> o;// 离散化int dec(int a[], int b[], int n, map <int, int>& mp) { copy(a + 1, a + n + 1, b + 1); sort(b + 1, b + n + 1); int m = unique(b + 1, b + n + 1) - b - 1; for(int i = 1; i <= n; i++) { mp[a[i]] = lower_bound(b + 1, b + m + 1, a[i]) - b; } return m;}int main() {// freopen("data.txt", "r", stdin); scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d%d", &a, &b, &h); rings[i] = ring(a, b, h); foo[i] = a; foo[n + i] = b; } // 离散化 m = dec(foo, bar, 2 * n, mp); o.build(1, 1, m); sort(rings + 1, rings + n + 1); for(int i = 1; i <= n; i++) { a = rings[i].a; b = rings[i].b; h = rings[i].h; // 查询d[j] if(mp[b] >= 2) { d = o.query(1, mp[b] - 1, 1, 1, m) + h; } else { d = h; } // tmp相当于d[i] tmp = o.query(mp[a], mp[a], 1, 1, m); // 将d[i]插入线段树 if(d > tmp) { o.update(mp[a], d, 1, 1, m); } // 用d[i]更新答案 ans = max(ans, d); } printf("%I64d\n", ans); return 0;}
- Codeforces Round #401 (div. 2)解题报告
- 【解题报告】Codeforces Round #401 (Div. 2)
- Codeforces Round #149 (Div. 2)解题报告
- Codeforces Round #180 (Div. 2) 解题报告
- Codeforces Round #190 (Div. 2) 解题报告
- Codeforces Round #191 (Div. 2) 解题报告
- Codeforces Round #189 (Div. 2) 解题报告
- Codeforces Round #142 (Div. 2) 解题报告
- Codeforces Round #229 (Div. 2) 解题报告
- Codeforces Round #241 (Div. 2) 解题报告
- Codeforces Round #262 (Div. 2)解题报告
- Codeforces Round #267 (Div. 2) 解题报告
- Codeforces Round #266 (Div. 2)解题报告
- Codeforces Round #268 (Div. 2) 解题报告
- Codeforces Round #271 (Div. 2) 解题报告
- Codeforces Round #274 (Div. 2) 解题报告
- Codeforces Round #276 (Div. 2) 解题报告
- Codeforces Round #277 (Div. 2) 解题报告
- cordova—— 监听手机软键盘出现和隐藏事件及获取软键盘的高度
- Leetcode题解
- 如何解决Android studio用HttpPost或者HttpGet从php获取信息在机子上显示乱码
- 元素最左出现练习
- 一个自己用的opencv历程
- 【解题报告】Codeforces Round #401 (Div. 2)
- C++指针函数与函数指针
- Rainbow实现代码高亮使用教程
- 去掉百度地图经度圈
- linux内核移植-DM9000C移植笔记
- Android Studio设置自定义字体
- 数据库事务的四大特性以及事务的隔离级别
- Mac 10.12 快速下载 Android 源码
- 【Python】学习笔记——-10、IO编程