Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) 解题报告(A~F)(E/F(hard)无)(示例
Posted zxytxdy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) 解题报告(A~F)(E/F(hard)无)(示例相关的知识,希望对你有一定的参考价值。
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) 解题报告(A~F)(E/F(hard)无)
A:Math Problem
目标区间右端点一定是所有给定区间左端点的最大值。
目标区间左端点一定是所有给定区间右端点的最小值。
输出即可,注意负数。
#include<bits/stdc++.h> using namespace std; int T, n, a, b; int main() { cin >> T; while(T--) { int a = 0, b = 1e9; scanf("%d", &n); for(int i = 1, x, y; i <= n; i++) { scanf("%d%d", &x, &y); a = max(a, x); b = min(b, y); } cout << max(0, a - b) << endl; } return 0; }
B:Box?
贪心。
假设输入序列为(a)序列,答案序列为(b)序列。
那么如果(a)序列上升了,(b)序列自然就是(a)序列的值。
如果(a)序列不变,那么就从没有出现的数字中取最小的数字。
贪心过程中注意特判无解情况。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int T, n; int a[maxn]; int b[maxn]; void solve() { scanf("%d", &n); set<int> s; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); s.insert(i); } int mx = 0; for(int i = 1; i <= n; i++) { if(a[i] > mx) { if(s.count(a[i])) { b[i] = a[i]; s.erase(b[i]); mx = a[i]; } else{ puts("-1"); return; } } else if(a[i] == mx) { if(*s.begin() > mx) { puts("-1"); return; } b[i] = *s.begin(); s.erase(s.begin()); } } for(int i = 1; i <= n; i++) printf("%d ", b[i]); puts(""); } int main() { scanf("%d", &T); while(T--) solve(); return 0; }
C:Messy?
首先这题初看很难做,但其实分析一下就可以转换为一个构造题。
首先长度为(n)的序列经过(n)次的操作一定能变成任意的括号序列。
那么其实我们只需要把序列构造成满足有(k)个合法前缀的情况。
怎么构造呢,先加入(k-1)个(()),然后剩余的全部都加上(((..)))这样的。
打个比方:
- 比如说样例(1)的(8 2),就先构造(()),然后加上(((())))。
- 样例(2)的(10 3),就构造(()()),然后加上(((())))。
之后根据最终的序列构造操作。
#include<bits/stdc++.h> #define PII pair<int, int> using namespace std; const int maxn = 2000 + 10; int T, n, k; string s, ans; void swap_str(int x, int y) { if(x > y) swap(x, y); while(x < y) { swap(s[x], s[y]); x++, y--; } } void get_op() { vector<PII> op; for(int i = 0; i < (int)s.size(); i++) { if(s[i] != ans[i]) { for(int j = i+1; j < (int)s.size(); j++) { if(s[i] != s[j]) { swap_str(i, j); op.push_back({i+1, j+1}); break; } } } } cout << op.size() << endl; for(auto x : op) printf("%d %d ", x.first, x.second); } int main() { scanf("%d", &T); while(T--) { scanf("%d%d", &n, &k); cin >> s; ans = ""; for(int i = 1; i <= k - 1; i++) ans += '(', ans += ')'; int tmp = n - (k-1) * 2; for(int i = 1; i <= tmp / 2; i++) ans += '('; for(int i = 1; i <= tmp / 2; i++) ans += ')'; //cout << ans << endl; get_op(); } return 0; }
D:Optimal Subsquences(Hard Version)
主席树+贪心。
我们需要满足子序列和最大,所以这(k)个数,一定是我们将序列从大到小排序后的前(k)个数字。
于是乎我要选择的(k)个数确定了。
同时我们需要保证字典序最小。
设(num)为第(k)大的元素,要想让字典序最小,那么我们需要做的就是让所有(num)出现的位置尽可能靠前,也就是尽可能的挑选(idx)小的元素。
所以我们记录序列(val)时同时记录序列的(id),之后按照(val)排序,(val)相等的两项让(id)小的在前。
之后用主席树维护(id)。
对于每次询问,找到对应的树与空树进行查询第(pos)大的数在原序列的位置,找到这个数即为答案。
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5 + 10; int n, m, mp[maxn]; //mp(i)表示第i次询问对应的那个版本的线段树 struct Arr { int v, id; }a[maxn]; int b[maxn]; bool cmp(Arr a, Arr b) { if(a.v == b.v) return a.id < b.id; return a.v > b.v; } struct Node{ int k, pos, id; }q[maxn]; bool cmp1(Node a, Node b){ return a.k < b.k; } int ans[maxn]; //-----------主席树部分 int sum[maxn<<5], ls[maxn<<5], rs[maxn<<5]; int rt[maxn<<5], tot; int build(int l, int r) { int root = ++tot; if(l == r) return root; int mid = (l + r) >> 1; ls[root] = build(l, mid); rs[root] = build(mid+1, r); return root; } int update(int pre, int l, int r, int k) { int root = ++tot; ls[root] = ls[pre], rs[root] = rs[pre], sum[root] = sum[pre] + 1; if(l == r) return root; int mid = (l + r) >> 1; if(k <= mid) ls[root] = update(ls[pre], l, mid, k); else rs[root] = update(rs[pre], mid+1, r, k); return root; } int query(int u, int v, int l, int r, int k) { if(l == r) return l; int x = sum[ls[v]] - sum[ls[u]]; int mid = (l + r) >> 1; if(k <= x) return query(ls[u], ls[v], l, mid, k); else return query(rs[u], rs[v], mid+1, r, k - x); } //------------------- void init() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &a[i].v); a[i].id = i; b[i] = a[i].v; } sort(a+1, a+1+n, cmp); scanf("%d", &m); for(int i = 1, x, y; i <= m; i++){ scanf("%d%d", &x, &y); q[i] = {x, y, i}; } sort(q+1, q+1+m, cmp1); } int main() { init(); rt[0] = build(1, n); int p = 1; for(int i = 1; i <= m; i++) { if(q[i].k < p) { mp[i] = mp[i-1]; //k相等的话用的是同一棵线段树 continue; } //插入对应的id for(int j = p; j <= q[i].k; j++) rt[j] = update(rt[j-1], 1, n, a[j].id); mp[i] = rt[q[i].k]; p = q[i].k + 1; } for(int i = 1; i <= m; i++) { int t = query(rt[0], mp[i], 1, n, q[i].pos); ans[q[i].id] = b[t]; } for(int i = 1; i <= m; i++) printf("%d ", ans[i]); return 0; }
F:Wrong Answer on test 233(Easy/Hard Version)
题意:
- 给定(n)道题,每道题有(k)个选项,有且仅有一个正确答案。
- 现在给你犯傻了,把第(1)题涂到了第(2)题,第(2)题涂到了第(3)题(,...,)第(n)题涂到了第(1)题。
- 给你原先(n)道题的答案,问你有多少种答案的可能,让你错误提交之后比你正确提交的分数高。
数据范围:
- (Easy Version 1leq nleq 2000)。
- (Hard Version 1leq nleq 10^5)。
思路((Easy Version)):
(dp)。
设(f(i,j))表示考虑到了第(i)题,交换后比交换前多得(j)分的结果数。
如果(h(i)==h(i+1))的话,(f(i,j)=f(i-1,j)),因为这时候交换并不会增加结果。
其他情况,(f(i,j)=f(i-1,j+1)+f(i-1,j-1)+(k-2)*f(i-1,j))
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e3 + 10; const int mod = 998244353; ll n, k, h[maxn], f[maxn][maxn<<1]; int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> k; for(int i = 1; i <= n; i++) cin >> h[i]; if(k == 1) { puts("0"); return 0; } f[0][2001] = 1; for(int i = 1; i <= n; i++) for(int j = 1; j < maxn<<1; j++) { if(h[i] == h[i%n+1]) f[i][j] = (f[i-1][j]*k)%mod; else f[i][j] = (f[i-1][j-1]+f[i-1][j+1]+f[i-1][j]*(k-2))%mod; } ll ans = 0; for(int i = 1; i <= n; i++) ans = (ans + f[n][2001+i]) % mod; cout << ans << endl; return 0; }
以上是关于Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) 解题报告(A~F)(E/F(hard)无)(示例的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B. Box 贪心
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B Box
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3)
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C. Messy 构造
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C Messy
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3