Codeforces Round #498 (Div. 3) 简要题解
[比赛链接]
https://codeforces.com/contest/1006
[题解]
Problem A. Adjacent Replacements
[算法]
将序列中的所有偶数替换为奇数即可
时间复杂度 : O(N)
[代码]
#include<bits/stdc++.h> using namespace std; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } int main() { int n; read(n); for (int i = 1; i <= n; i++) { int x; read(x); if (x & 1) printf("%d ",x); else printf("%d ",x - 1); } printf("\n"); return 0; }
Problem B. Polycarp's Practice
[算法]
要求k天的和最大化 , 我们不妨将这些数加入一个堆中 , 取出前k大值
构造一组合法的解即可
时间复杂度 : O(NlogN)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 2010 int ans[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } int main() { int n , k , t = 0 , value = 0; static priority_queue< pair<int,int> > q; read(n); read(k); for (int i = 1; i <= n; i++) { int x; read(x); q.push(make_pair(x,i)); } while (t < k) { value += q.top().first; ans[++t] = q.top().second; q.pop(); } sort(ans + 1,ans + k + 1); printf("%d\n",value); for (int i = 1; i <= k - 1; i++) printf("%d ",ans[i] - ans[i - 1]); printf("%d\n",n - ans[k - 1]); return 0; }
Problem C. Three Parts of the Array
[算法]
用Two Pointers扫描求出答案即可
也可以通过std :: set等数据结构求解
时间复杂度 : O(N)
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e6 + 10; long long a[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } int main() { long long n; read(n); for (int i = 1; i <= n; i++) read(a[i]); long long l = 1 , r = n; long long s1 = 0 , s2 = 0 , ans = 0; while (l <= r) { if (s1 < s2) { s1 += a[l++]; if (s1 == s2) ans = s1; } else if (s2 < s1) { s2 += a[r--]; if (s1 == s2) ans = s1; } else { if (l == r) break; s1 += a[l++]; s2 += a[r--]; if (s1 == s2) ans = s1; } } printf("%I64d\n",ans); return 0; }
Problem D. Two Strings Swaps
[算法]
枚举字符串的前[n/2]个字符 ([x]表示向下取整) ,
如果字符串a和字符串b的第i个字符和第(n - i + 1)个字符共有4个不同的字符 , 显然对答案产生2的贡献
如果有3个不同字符 , 当字符串a的第i个字符和第(n - i + 1)个字符相同 , 则对答案产生2的贡献 , 否则对答案产生1的贡献
如果有2个不同字符 , 如果第a的第i个字符出现次数不为2 , 则对答案产生1的贡献
当字符串长度为奇数时 , 若字符串a的第(n + 1) / 2和字符串b的第(n + 1) / 2个字符不相等 , 则对答案产生1的贡献
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 10; int n , ans; char a[MAXN],b[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } int main() { scanf("%d",&n); scanf("%s%s",a + 1,b + 1); for (int i = 1; i <= n / 2; i++) { map< char,int > mp; mp.clear(); mp[a[i]]++; mp[a[n - i + 1]]++; mp[b[i]]++; mp[b[n - i + 1]]++; if ((int)mp.size() == 4) ans += 2; if ((int)mp.size() == 3) { if (a[i] == a[n - i + 1]) ans += 2; else ans++; } if ((int)mp.size() == 2) { if (mp[a[i]] != 2) ans++; } } if ((n & 1) && a[n / 2 + 1] != b[n / 2 + 1]) ans++; printf("%d\n",ans); return 0; }
Problem E. Military Problem
[算法]
不妨先求出整棵树的DFS序 , 记为Dfn[]
然后 , 我们用Pos[i]表示DFS序为i的节点
对于询问(ui , ki) , 显然 , 答案为Pos[Dfn[ui] - 1 + k]
时间复杂度 : O(N)
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 10; int n , q , timer; int size[MAXN],ans[MAXN],depth[MAXN],dfn[MAXN]; vector< int > G[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void dfs(int u) { size[u] = 1; dfn[u] = ++timer; ans[timer] = u; for (unsigned i = 0; i < G[u].size(); i++) { depth[G[u][i]] = depth[u] + 1; dfs(G[u][i]); size[u] += size[G[u][i]]; } } int main() { read(n); read(q); for (int i = 2; i <= n; i++) { int x; read(x); G[x].push_back(i); } dfs(1); while (q--) { int u , k; read(u); read(k); if (size[u] < k) { printf("-1\n"); continue; } printf("%d\n",ans[dfn[u] + k - 1]); } return 0; }
Problem F. Xor Paths
[算法]
显然 , 所有的路径长度都为(n + m - 1)
考虑使用Meet-In-The-Middle( 中途相遇法 )
第一遍DFS求出前(n + m - 1)步 , 每个位置上出现的异或和情况数
第二遍DFS求出后(n + m) / 2步 , 根据第一遍DFS求出的情况数统计答案
时间复杂度 : O(2 ^ ((n + m - 2) / 2) * (n + m - 2) / 2)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 25 #define MAXS 100005 int n , m; long long a[MAXN][MAXN]; long long val , ans = 0; map< long long,int > cnt[MAXN][MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline bool valid(int x,int y) { return x >= 1 && x <= n && y >= 1 && y <= m; } inline void dfs1(int x,int y,int step,long long k) { if (step == (n + m - 1) / 2) { cnt[x][y][k]++; return; } if (valid(x + 1,y)) dfs1(x + 1,y,step + 1,k ^ a[x + 1][y]); if (valid(x,y + 1)) dfs1(x,y + 1,step + 1,k ^ a[x][y + 1]); } inline void dfs2(int x,int y,int step,long long k) { if (step == (n + m) / 2) { if (valid(x,y - 1)) ans += cnt[x][y - 1][val ^ k]; if (valid(x - 1,y)) ans += cnt[x - 1][y][val ^ k]; return; } if (valid(x - 1,y)) dfs2(x - 1,y,step + 1,k ^ a[x - 1][y]); if (valid(x,y - 1)) dfs2(x,y - 1,step + 1,k ^ a[x][y - 1]); } int main() { read(n); read(m); read(val); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { read(a[i][j]); } } if (n == 1 && m == 1) { if (a[1][1] == val) printf("1\n"); else printf("0\n"); return 0; } dfs1(1,1,1,a[1][1]); dfs2(n,m,1,a[n][m]); printf("%I64d\n",ans); return 0; }