cf edu 1600

1|0600A. Extract Numbers


划分一下然后特判即可。

#include<bits/stdc++.h> using namespace std; int32_t main() { string s , t = ""; cin >> s; vector<string> a , b; s += ";"; for( auto i : s ){ if( i == ',' or i == ';' ){ if( t == "0" ) a.push_back(t); else if( t == "" ) b.push_back(t); else if( t[0] == '0' ) b.push_back(t); else{ int f = 1; for( auto j : t ){ if( j >= '0' && j <= '9' ) continue; f = 0; break; } if(f) a.push_back(t); else b.push_back(t); } t = ""; } else t += i; } if( a.empty() ) cout << "-\n"; else{ cout << "\"" << a.front(); for( int i = 1 ; i < a.size() ; i ++ ) cout << "," << a[i]; cout << "\"\n"; } if( b.empty() ) cout << "-\n"; else{ cout << "\"" << b.front(); for( int i = 1 ; i < b.size() ; i ++ ) cout << "," << b[i]; cout << "\"\n"; } return 0; }

2|01342C. Yet Another Counting Problem


#include<bits/stdc++.h> using namespace std; #define int long long const int N = 40005; int len, p[N]; void build(int a, int b) { len = a * b, p[0] = 0; for (int i = 1; i <= len; i++) p[i] = p[i - 1] + ((i % a) % b != (i % b) % a); return; } int query(int l) { return p[len] * (l / len) + p[l % len]; } int query(int l, int r) { return query(r) - query(l - 1); } void solve() { int a, b, q; cin >> a >> b >> q; build(a,b); for (int l, r; q; q--) cin >> l >> r, cout << query(l, r) << " "; cout << "\n"; return; } int32_t main() { int t; cin >> t; while (t--) solve(); return 0; }

3|01455D. Sequence and Swaps


可以注意到的是每次能够被交换的数一定是递增的,同理每次能够放回去的数也是递增的,所以选择的i一定是递增的。所以我们从小到大枚举i遇见可以交换的就一定要交换,统计交换次数即可。

#include<bits/stdc++.h> using namespace std; #define mp make_pair #define int long long const int N = 205; int g[N][N][N], a[N], b[N]; int read() { int x = 0, ch = getchar(); while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x; } void solve() { int n = read(), x = read(); vector<int> a(n); for (auto &i: a) i = read(); if(is_sorted(a.begin(), a.end())){ cout << "0\n"; return; } int res = 0; for( int i = 0 ; i < n ; i ++ ){ if( a[i] > x ) swap( a[i] , x ) , res ++; if(is_sorted(a.begin(), a.end())) break; } if(is_sorted(a.begin(), a.end())) cout << res << "\n"; else cout << "-1\n"; return; } int32_t main() { for (int t = read(); t; t--) solve(); return 0; }

4|01398C. Good Subarrays


求前缀和后,则题目要求aral1=r(l1)。所以可以转换为arr=al1(l1)。这样我们统计aii出现的次数,然后用组合数就可以计算了。

#include<bits/stdc++.h> using namespace std; #define mp make_pair #define int long long int res = LLONG_MIN; vector<int> v, f; vector<vector<int>> e; void solve() { int n; cin >> n; string s; cin >> s; vector<int> a; a.push_back(0); for (auto i: s) a.push_back(i - '0'); for( int i = 1 ; i <= n ; i ++ ) a[i] += a[i-1]; map<int, int> cnt; for (int i = 0; i <= n; i++) cnt[a[i] - i]++; int res = 0; for (auto [k, v]: cnt) res += v * (v - 1) / 2; cout << res << "\n"; return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

5|01389B. Array Walk


我们枚举向左跳i步,则向右跳ki步,所以最终可以跳到k2i步。然后就是选择最大的两个相邻的数反复走i次即可。

#include<bits/stdc++.h> using namespace std; #define int long long void solve() { int n, k, z; cin >> n >> k >> z; vector<int> a(n); for (auto &i: a) cin >> i; int res = 0; for (int i = 0; i <= z; i++) { int pos = k - 2 * i; if( pos < 0 ) continue; int sum = 0 , m = 0; for( int i = 0 ; i <= pos ; i ++ ){ if( i < n-1 ) m = max( m , a[i] + a[i+1] ); sum += a[i]; } res = max( res , sum + m * i ); } cout << res << "\n"; return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

6|01373D. Maximum Sum on Even Positions


首先要想到的是有效的翻转区间一定是一段长度为偶数的区间。

如果翻转的区间是以奇数开头的,则对于区间内所有奇数下标的点i相当于a[i]a[i1]的贡献。

而我们要选择一个字段贡献最大,这样就转换成了最大字段和的问题。

翻转区间以偶数开头类似,只是贡献变为了a[i1]a[i]

#include<bits/stdc++.h> using namespace std; #define int long long void solve() { int n, ans = 0, res = 0; cin >> n; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; if (i % 2 == 0) res += a[i]; } for (int i = 1, cnt = 0; i < n; i += 2) { cnt = max(0ll, cnt + a[i] - a[i - 1]); ans = max(ans, cnt); } for (int i = 2, cnt = 0; i < n; i += 2) { cnt = max(0ll, cnt + a[i - 1] - a[i]); ans = max(ans, cnt); } cout << ans + res << "\n"; return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

7|01334C. Circle of Monsters


第一个攻击的怪兽无法接受前一个怪兽造成的爆炸伤害。最朴素的的方法自然是枚举第一个攻击的怪兽,然后依次攻击后面的怪兽。其实可以发现的是,每一个怪兽造成的受到的爆炸伤害是min(a[i],b[i1])。所以其实我么可以贪心的选择受到爆炸伤害最小的怪兽作为第一个怪兽。

#include<bits/stdc++.h> using namespace std; #define int long long void solve() { int cnt = 0, n, inc = LLONG_MAX; cin >> n; vector<int> a(n), b(n); for (int i = 0; i < n; i++) cin >> a[i] >> b[i]; for (int i = 0, ni, dec; i < n; i++) { ni = (i + 1) % n; dec = min(a[ni], b[i]); cnt += a[ni] - dec; inc = min(inc, dec); } cout << cnt + inc << "\n"; return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

8|01295C. Obtain The String


首先我们对s串来进行预处理,处理出nex[i][j]数组表示位置i之后字母j第一次出现的位置。

这样的话,我们用一个指针标记对于s串当前匹配的到位置,然后每次贪心的向后移动即可。

#include<bits/stdc++.h> using namespace std; #define int long long void solve() { string s, t; cin >> s >> t; vector nxt(s.size() + 1, vector<int>(26, INT_MAX)); for (int i = s.size() - 1; i >= 0; i--) { nxt[i] = nxt[i + 1]; nxt[i][s[i] - 'a'] = i; } int res = 1; for (int i = 0, pos = 0; i < t.size() && res < INT_MAX; i++) { if (pos == s.size()) pos = 0, res++; if (nxt[pos][t[i] - 'a'] == INT_MAX) pos = 0, res++; if (nxt[pos][t[i] - 'a'] == INT_MAX && pos == 0) { res = INT_MAX; break; } pos = nxt[pos][t[i] - 'a'] + 1; } if (res == INT_MAX) res = -1; cout << res << "\n"; return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

9|01303C. Perfect Keyboard


我自己的想法实际上是建图,然后跑一个类似拓扑序的东西?但是看题解明显要简单很多。

题解的思路其实就是贪心的放就可以了。我们遍历密码序列,序列中每一个元素都有两种状态,在答案序列中和不在答案序列中。如果在答案序列中就要检查和密码序列的上一位是否相邻?如果不在则一点要放在密码序列上一位的两侧,检查两侧是否可以放下。

#include<bits/stdc++.h> using namespace std; #define int long long void solve() { string s; cin >> s; vector<bool> used(26); used[s[0] - 'a'] = true; string t(1, s[0]); int pos = 0; for (int i = 1; i < s.size(); i++) { if (used[s[i] - 'a']) { if (pos > 0 && t[pos - 1] == s[i]) pos--; else if (pos + 1 < t.size() && t[pos + 1] == s[i]) pos++; else { cout << "NO\n"; return; } } else { if (pos == 0) t = s[i] + t; else if( pos == t.size() - 1 ) t += s[i] ,pos ++; else { cout << "NO\n"; return ; } used[s[i]-'a'] = true; } } for( char i = 'a' ; i <= 'z' ; i ++ ) if( !used[i-'a'] ) t += i; cout << "YES\n" << t << "\n"; return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

10|01327C. Game with Chips


注意到限制并不是2(n+m)而是2nm。点的位置根本不影响答案,先把所有的点移动到一个角,然后遍历整张图即可。

#include<bits/stdc++.h> using namespace std; #define int long long int32_t main() { int n, m, k; cin >> n >> m >> k; if( n * m == 1 ){ cout << "0\n"; return 0; } string res = ""; for (int i = 1; i < n; i++) res += "U"; for (int i = 1; i < m; i++) res += "L"; for (int i = 1; i <= n; i++) { if (i & 1) { for (int j = 1; j < m; j++) res += "R"; } else { for (int j = 1; j < m; j++) res += "L"; } if ( i != n ) res += "D"; } cout << res.size() << "\n" << res << "\n"; return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/17606981.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示