OUC_2014 Spring Training 省赛组队训练赛 #1总结
2014-04-20 15:11
295 查看
A线段树或者树状数组,离线处理,hash,数组开大些 hdu3333
B题 略
C题二分图匹配求最大独立集,二分图中最大独立集 = 节点数 - 最大匹配数 hdu3335
D题 Kmp + dp
EF题 略
G题 最短路 + dp 有重边
I题ac自动机 + dp
J题 是否所给有向图中存在环 floyd求传递闭包,拓扑排序,tarjan求联通分量都可以解决
#include <iostream> #include <cstdio> #include <string.h> #include <map> using namespace std; #define MAXN 300000 + 10 map <__int64, int> hash; int n, m; __int64 val[MAXN], ans[MAXN], c[MAXN]; struct Node { int l, r, index; }q[MAXN]; __int64 lowbit(int x) { return x & (-x); } __int64 sum(int n) { __int64 sum = 0; while (n > 0) { sum += c ; n -= lowbit(n); } return sum; } void change(int i, __int64 x) { while (i <= n) { c[i] = c[i] + x; i += lowbit(i); } } bool cmp(Node a, Node b) { return a.r < b.r; } void input() { int t; cin >> t; while (t--) { scanf("%d", &n); hash.clear(); memset(c, 0, sizeof(c)); for (int i = 1; i <= n; i++) { scanf("%I64d", &val[i]); } scanf("%d", &m); for (int i = 0; i < m; i++) { scanf("%d %d", &q[i].l, &q[i].r); q[i].index = i; } sort(q, q + m, cmp); for (int i = 0, pos = 1; i < m; i++) { while (pos <= n && pos <= q[i].r) { if (hash[val[pos]]) { change(hash[val[pos]], -val[pos]); } change(pos, val[pos]); hash[val[pos]] = pos; pos++; } ans[q[i].index] = sum(q[i].r) - sum(q[i].l - 1); } for (int i = 0; i < m; i++) { printf("%I64d\n",ans[i]); } } } int main() { input(); return 0; }
B题 略
C题二分图匹配求最大独立集,二分图中最大独立集 = 节点数 - 最大匹配数 hdu3335
#include <iostream> #include <cstdio> #include <algorithm> #include <string.h> #include <string> using namespace std; #define MAXN 1000 * 10 int n; bool vis[MAXN]; int match[MAXN]; __int64 node[MAXN]; struct Edge { int u, v, next; }edge[1000 * MAXN]; int head[MAXN], e; void add(int u, int v) { edge[e].v = v; edge[e].next = head[u]; head[u] = e++; } void init() { e = 0; memset(head, -1, sizeof(head)); memset(match, -1, sizeof(match)); } bool dfs(int u) { for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (!vis[v]) { vis[v] = true; if (match[v] == -1 || dfs(match[v])) { match[v] = u; return true; } } } return false; } int solve() { int res = 0; for (int i = 0; i < n; i++) { memset(vis, false, sizeof(vis)); if (dfs(i)) { res++; } } return res; } void input() { int t; cin >> t; while (t--) { init(); scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%I64d", &node[i]); } sort(node, node + n); int temp = 0; for (int i = 1; i < n; i++) { if (node[temp] != node[i]) { node[++temp] = node[i]; } } n = temp + 1; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (node[j] % node[i] == 0) { add(i, j); } } } cout << n - solve() << endl; } } int main() { input(); return 0; }
D题 Kmp + dp
#include <iostream> #include <string.h> using namespace std; #define MAXN 200000 + 100 int next[MAXN]; string str; void getN() { next[0] = -1; for (int i = 1, j = -1; i < str.length(); i++) { while (j >= 0 && str[i] != str[j + 1]) { j = next[j]; } if (str[i] == str[j + 1]) { j++; } next[i] = j; } } int c[MAXN]; void input() { int cases, n; long long sum = 0; cin >> cases; while (cases--) { sum = 0; memset(c, 0, sizeof(c)); cin >> n; cin >> str; getN(); for (int i = 0; i < n; i++) { next[i]++; } for (int i = 1; i <= n; i++) { c[i] = (c[next[i - 1]] + 1) % 10007; sum = (sum + c[i]) % 10007; } cout << sum << endl; } } int main() { input(); return 0; }
EF题 略
G题 最短路 + dp 有重边
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <string.h> #include <string> using namespace std; #define MAXN 150 #define inf 100000000 int c[MAXN][MAXN]; int val[MAXN]; int dp[10000 * MAXN]; void input() { int t; int u, v, w, n, m; cin >> t; while (t--) { scanf("%d %d", &n, &m); memset(dp, 0, sizeof(dp)); for (int i = 0; i <= n; i++) { for (int j = 0; j <= n; j++) { c[i][j] = (i == j ? 0 : inf); } } for (int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); c[u][v] = c[v][u]= min(c[u][v], w); } for (int k = 0; k <= n; k++) { for (int i = 0; i <= n; i++) { for (int j = 0; j <= n; j++) { if (c[i][k] + c[k][j] < c[i][j]) { c[i][j] = c[i][k] + c[k][j]; } } } } int sum = 0, v = 0; for (int i = 1; i <= n; i++) { scanf("%d", &val[i]); sum += val[i]; if (c[0][i] != inf) { v += c[0][i]; } } sum /= 2; for (int i = 1; i <= n; i++) { if (c[0][i] != inf) for (int j = v; j >= c[0][i]; j--) { dp[j] = max(dp[j], dp[j - c[0][i]] + val[i]); } } bool ok = false; for (int i = 1; i <= v; i++) { if (dp[i] > sum) { cout << i << endl; ok = true; break; } } if (!ok) { cout << "impossible" << endl; } } } int main() { input(); return 0; }
I题ac自动机 + dp
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <string.h> #include <string> #include <queue> using namespace std; #define MAXN 50 + 10 #define MAXNODE 500 + 10 char c[MAXN], str[MAXN]; struct Trie { int next[MAXNODE][4], fail[MAXNODE]; int ends[MAXNODE]; int root, L; int newnode() { for (int i = 0; i < 4; i++) { next[L][i] = -1; } ends[L++] = 0; return L - 1; } void init() { L = 0; root = newnode(); } int getch(char ch) { if (ch == 'A') return 0; if (ch == 'C') return 1; if (ch == 'G') return 2; if (ch == 'T') return 3; } void inserts(char *ch) { int len = strlen(ch); int now = root; for (int i = 0; i < len; i++) { if (next[now][getch(ch[i])] == -1) { next[now][getch(ch[i])] = newnode(); } now = next[now][getch(ch[i])]; } ends[now]++; } void build() { queue <int> Q; fail[root] = root; for (int i = 0; i < 4; i++) { if (next[root][i] == -1) { next[root][i] = root; } else { fail[next[root][i]] = root; Q.push(next[root][i]); } } while (!Q.empty()) { int now = Q.front(); Q.pop(); ends[now] += ends[fail[now]]; for (int i = 0; i < 4; i++) { if (next[now][i] == -1) { next[now][i] = next[fail[now]][i]; } else { fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); } } } } int dp[MAXNODE][11 * 11 * 11 * 11 + 10]; int bit[4]; int num[4]; int solve() { int len = strlen(str); memset(num, 0, sizeof(num)); for (int i = 0; i < len; i++) { num[getch(str[i])]++; } bit[0] = (num[1] + 1) * (num[2] + 1) * (num[3] + 1); bit[1] = (num[2] + 1) * (num[3] + 1); bit[2] = (num[3] + 1); bit[3] = 1; memset(dp, -1, sizeof(dp)); dp[root][0] = 0; for (int a = 0; a <= num[0]; a++) { for (int b = 0; b <= num[1]; b++) { for (int c = 0; c <= num[2]; c++) { for (int d = 0; d <= num[3]; d++) { int s = a * bit[0] + b * bit[1] + c * bit[2] + d * bit[3]; for (int i = 0; i < L; i++) { if (dp[i][s] >= 0) for (int k = 0; k < 4; k++) { if (k == 0 && a == num[0])continue; if (k == 1 && b == num[1])continue; if (k == 2 && c == num[2])continue; if (k == 3 && d == num[3])continue; dp[next[i][k]][s + bit[k]] = max(dp[next[i][k]][s + bit[k]],dp[i][s] + ends[next[i][k]]); } } } } } } int ans = 0; int st = num[0] * bit[0] + num[1] * bit[1] + num[2] * bit[2] + num[3] * bit[3]; for (int i = 0; i < L; i++) { ans = max(ans, dp[i][st]); } cout << ans << endl; } }ac; void input() { int n, cases = 0; while (cin >> n, n) { ac.init(); for (int i = 0; i < n; i++) { scanf("%s", c); ac.inserts(c); } ac.build(); scanf("%s", str); cout << "Case " << ++cases << ": "; ac.solve(); } } int main() { input(); return 0; }
J题 是否所给有向图中存在环 floyd求传递闭包,拓扑排序,tarjan求联通分量都可以解决
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <string.h> #include <string> using namespace std; #define MAXN 200 int c[MAXN][MAXN]; void input() { int n, m, u, v; while (cin >> n >> m, n) { memset(c, 0, sizeof(c)); for (int i = 0; i < m; i++) { scanf("%d %d", &u, &v); c[u][v] = 1; } for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (c[i][k] && c[k][j]) { c[i][j] = 1; } } } } bool ok = true; for (int i = 0; i < n; i++) { if (c[i][i]) { ok = false; break; } } cout << (ok ? "YES" : "NO") << endl; } } int main() { input(); return 0; }
相关文章推荐
- 2014 多校联合训练赛6 Fighting the Landlords
- HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)
- 总结2014——迷茫以及迷茫过后的坚持
- 女程序猿2014总结(修改)
- 13暑假集训#1 总结
- 2014acm亚洲赛总结
- 2014ACM亚洲区域北京邀请赛总结
- 2014的总结
- 2014学习总结
- 2014武汉大学acm邀请赛总结
- 总结2013,奋斗2014!
- SCOI2014总结
- 2014青岛理工大学ACM邀请赛总结
- 【总结】2014新生暑假个人排位赛03
- CSU-ACM2014暑假集训基础组训练赛(1) 解题报告
- 省赛组队赛3 比赛总结
- IT面试2014校招笔试面试全面总结分析回顾(有点早,仅供参考)
- 2014第35周三jquery最近用到的内容总结
- 2014南邮暑期集训组队赛3 BCD题题解