Educational Codeforces Round 32【solved: 6 / 7】(F待补)
2017-11-10 16:51
585 查看
A - Local Extrema (模拟)
思路:根据题意模拟即可
B - Buggy Robot (简单思维)
思考一下左右上下对称即可
C - K-Dominant Character (二分)
二分长度,枚举26个字母,挨个check一遍。
D - Almost Identity Permutations(错排)
思路:错排公式,枚举0-k个不错排的人。加和即可
E - Maximum Subsequence (折半搜索)
思路:
对前一半个数字进行状压dp,找到他们加和的结果,丢到vector里面去重。然后去对后一半的数字进行相同的操作,去前一半已经计算出的结果里找到匹配项。
前一半的数的加和的结果 所在的 集合叫做S好了。 然后后一半数字计算出来的叫做val好了。取模是对m取模的。
那么我们找的时候,考虑到取模的特殊性,一定是S中,小于m-val的数里头最大的,或者是S当中最大的,和val加和,才有可能产生最大值。前者是加和以后最接近m,后者是希望取模以后最接近m。
G - Xor-MST (01字典树+贪心+最小异或生成树)
给你n个点,每条边的边权是两个点的异或和,问你形成最小生成树,需要的代价是多少。(n≤200000,ai≤230)
思路:把数都插到字典树里面,然后考虑两个数的合并,最小代价的话,应该是尽可能相同的多,所以可以看做是两个子树的合并,那么插的时候记录一个siz,采取dfs,发现点root有左右儿子结点的时候,就可以合并了,合并的方式是枚举较小的子树中的每一个数,然后跑到另一个子树里去查最小异或和,更新答案。
思路:根据题意模拟即可
#include <bits/stdc++.h> using namespace std; int a[1005]; int main() { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); int maxx = 0, minn = 0; for(int i = 1; i <= n; i++) { if(i == 1 || i == n) continue; if(a[i] > a[i - 1] && a[i] > a[i + 1]) maxx++; if(a[i] < a[i - 1] && a[i] < a[i + 1]) minn++; } printf("%d\n", maxx + minn); return 0; }
B - Buggy Robot (简单思维)
思考一下左右上下对称即可
#include <bits/stdc++.h> using namespace std; char s[1005]; int main() { int n; scanf("%d", &n); scanf("%s", s); int cntl = 0, cntr = 0, cntu = 0, cntd = 0; for(int i = 0; i < n; i++) { if(s[i] == 'L') cntl++; else if(s[i] == 'R') cntr++; else if(s[i] == 'U') cntu++; else if(s[i] == 'D') cntd++; } int ans = 0; ans = min(cntl, cntr) * 2 + min(cntu, cntd) * 2; printf("%d\n", ans); return 0; }
C - K-Dominant Character (二分)
二分长度,枚举26个字母,挨个check一遍。
#include <bits/stdc++.h> using namespace std; char s[100000 + 5]; int cnt[30], len; bool judge(int mid) { int n = len; bool ok = false; for(int i = 0; i < 26; i++) { char ch = 'a' + i; int cnt = 0; for(int j = 0; j < mid; j++) if(s[j] == ch) cnt++; if(cnt == 0) continue; for(int j = mid; j f922 < n; j++) { if(s[j - mid] == ch) cnt--; if(s[j] == ch) cnt++; if(cnt == 0) break; } if(cnt == 0) continue; else return true; } return false; } int main() { scanf("%s", s); len = strlen(s); int lb = 1, rb = len; while(lb < rb) { int mid = (lb + rb) / 2; if(judge(mid)) rb = mid; else lb = mid + 1; } printf("%d\n", rb); return 0; }
D - Almost Identity Permutations(错排)
思路:错排公式,枚举0-k个不错排的人。加和即可
#include <bits/stdc++.h> using namespace std; int d[] = {0, 0, 1, 2, 9, 44}; long long C(int n, int m) { long long ret = 1; for(int i = n - m + 1; i <= n; i++) ret = ret * i; for(int i = 1; i <= m; i++) ret /= i; return ret; } int main() { int n, k; scanf("%d%d", &n, &k); long long ans = 0; for(int i = 0; i <= k; i++) { long long temp = 1LL * C(n, i) * d[i]; ans += temp; } printf("%lld\n", ans + 1); return 0; }
E - Maximum Subsequence (折半搜索)
思路:
对前一半个数字进行状压dp,找到他们加和的结果,丢到vector里面去重。然后去对后一半的数字进行相同的操作,去前一半已经计算出的结果里找到匹配项。
前一半的数的加和的结果 所在的 集合叫做S好了。 然后后一半数字计算出来的叫做val好了。取模是对m取模的。
那么我们找的时候,考虑到取模的特殊性,一定是S中,小于m-val的数里头最大的,或者是S当中最大的,和val加和,才有可能产生最大值。前者是加和以后最接近m,后者是希望取模以后最接近m。
#include <bits/stdc++.h> using namespace std; int a[40]; int main() { int n, m; scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) scanf("%d", &a[i]); int lpart = (n + 1) / 2, rpart = n - lpart; vector<int>vec; for(int S = 0; S < (1 << lpart); S++) { int temp = 0; for(int j = 0; j < lpart; j++) { if(S & (1 << j)) temp = (temp + a[j]) % m; } vec.push_back(temp); } sort(vec.begin(), vec.end()); vec.resize(unique(vec.begin(), vec.end()) - vec.begin()); int maxx = *max_element(vec.begin(), vec.end()); int ans = 0; for(int S = 0; S < (1 << rpart); S++) { int temp = 0; for(int j = lpart; j < n; j++) { int idx = j - lpart; if(S & (1 << idx)) temp = (temp + a[j]) % m; } ans = max(ans, (temp + maxx) % m); int lb = 0, rb = vec.size() - 1; while(lb < rb) { int mid = (lb + rb + 1) / 2; if(vec[mid] < m - temp) lb = mid; else rb = mid - 1; } ans = max(ans, (temp + vec[rb]) % m); } printf("%d\n", ans); return 0; }
G - Xor-MST (01字典树+贪心+最小异或生成树)
给你n个点,每条边的边权是两个点的异或和,问你形成最小生成树,需要的代价是多少。(n≤200000,ai≤230)
思路:把数都插到字典树里面,然后考虑两个数的合并,最小代价的话,应该是尽可能相同的多,所以可以看做是两个子树的合并,那么插的时候记录一个siz,采取dfs,发现点root有左右儿子结点的时候,就可以合并了,合并的方式是枚举较小的子树中的每一个数,然后跑到另一个子树里去查最小异或和,更新答案。
#include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 200000 + 5; typedef long long LL; long long ans, cost; struct Trie { int ch[32*maxn][2], siz[32*maxn], val[32*maxn], num[32*maxn], sz; int up = 30; init(){sz = 1;memset(ch[0], 0, sizeof(ch[0]));} void Insert(int x) { int u = 0; for(int i = up; i >= 0; i--) { int c = ((x >> i) & 1); if(ch[u][c] == 0) { memset(ch[sz], 0, sizeof(ch[sz])); num[sz] = val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; num[u] ++; } val[u] = x; } int getSize(int x) { if(!ch[x][0] && !ch[x][1]) return siz[x] = 1; if(ch[x][0]) siz[x] += getSize(ch[x][0]); if(ch[x][1]) siz[x] += getSize(ch[x][1]); return siz[x]; } void dfs(int x) { if(ch[x][0]) dfs(ch[x][0]); if(ch[x][1]) dfs(ch[x][1]); if(ch[x][0] && ch[x][1]) {//要合并root = x,这个结点的左右儿子。 cost = INF; int lson = ch[x][0], rson = ch[x][1]; if(siz[lson] < siz[rson]) calc(lson, x); else calc(rson, x); ans += cost; } } void calc(int x, int pre) {//遍历root左右子树中较小一颗的所有数。 if(ch[x][0]) calc(ch[x][0], pre); if(ch[x][1]) calc(ch[x][1], pre); if(!ch[x][0] && !ch[x][1]) { int now = query(val[x], pre); if(cost > (val[now] ^ val[x])) { cost = (val[now] ^ val[x]); } } } int query(int x, int pre) {//pre标记之前要合并左右儿子的根结点root。 int u = 0; for(int i = up; i >= 0; i--) { int c = ((x >> i) & 1); if(ch[u][c] == 0) c = 1 - c; if(u == pre) c = 1 - c; u = ch[u][c]; } return u; } }trie; int main() { trie.init(); int n; scanf("%d", &n); for(int i = 1; i <= n; i++) { int x; scanf("%d", &x); trie.Insert(x); } trie.getSize(0); trie.dfs(0); printf("%lld\n", ans); return 0; }
相关文章推荐
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Educational Codeforces Round 32 B题 Buggy Robot(模拟)
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Educational Codeforces Round 32
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Educational Codeforces Round 32 题解
- Educational Codeforces Round 32 E 折半枚举
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Educational Codeforces Round 32 F. Connecting Vertices
- Educational Codeforces Round 32 A. Local Extrema(模拟水题)
- Educational Codeforces Round 32 B. Buggy Robot(模拟)
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Educational Codeforces Round 32 C. K-Dominant Character(模拟)
- Educational Codeforces Round 32
- Educational Codeforces Round 32 A B C
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子
- Codeforces-Educational Codeforces Round 32-(A,B,C,D)
- Educational Codeforces Round 32 G. Xor-MST 01字典树+二叉树 (板子