2019年07月25日23:56:32
https://www.hackerrank.com/challenges/sam-and-substrings/editorial
求一个数字字符串所有子串数字之和,dp[i]表示以第i个字符结尾的总和,列举所有出来可得到递推公式。
2018-05-08 16:56:08
https://csacademy.com/contest/archive/task/swap_pairing/statement/
题目意思是问,给定一个数组,每个数字都精确出现了两次。每一个操作可以交换相邻的两个数字。
要求目标是相同的数字挨在一起,求最小的操作次数。
贪心的做法是最左边的数字肯定不要动,让最右边的数字靠过来。这样最优。然后就是第一次先匹配a[1], 然后再匹配a[2]......这样。
统计的时候用树状数组维护一下就好
#include <cstdio> #include <cstring> #include <cstdlib> #include <string> #include <iostream> #include <assert.h> #include <map> using namespace std; const int maxn = 1e5 + 20; int c[maxn]; int lowbit(int pos) { return pos & (-pos); } int ask(int pos) { int ans = 0; while (pos > 0) { ans += c[pos]; pos -= lowbit(pos); } return ans; } void update(int pos, int val) { while (pos < maxn) { c[pos] += val; pos += lowbit(pos); } } int a[maxn]; bool need[maxn]; map<int, int> mp; void work() { int n; cin >> n; for (int i = 1; i <= n; ++i) { cin >> a[i]; } for (int i = n; i >= 1; --i) { if (mp.count(a[i]) == 0) { mp[a[i]] = i; } else need[i] = true; } long long int ans = 0; for (int i = 1; i <= n; ++i) { if (!need[i]) continue; ans += mp[a[i]] - i - 1; ans -= ask(mp[a[i]]) - ask(i - 1); update(mp[a[i]], 1); } cout << ans << endl; } int main() { // freopen("data.txt", "r", stdin); work(); return 0; }
被卡了返回vector<long long int>
又暂时学不会返回引用,惨。。cpp白学
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 2; const long long int inf = (long long int) 1e18; const int oo = (int) 1e9; struct segTree { int L, R; long long int sum; int mx, mi; } seg[maxn << 2]; int root; int build(int L, int R) { int now = ++root; seg[now].sum = 0; seg[now].mx = -oo; seg[now].mi = oo; if (L == R) { seg[now].sum = seg[now].mi = seg[now].mx = 0; return now; } int mid = (L + R) >> 1; seg[now].L = build(L, mid); seg[now].R = build(mid + 1, R); seg[now].sum = seg[seg[now].L].sum + seg[seg[now].R].sum; seg[now].mx = max(seg[seg[now].L].mx, seg[seg[now].R].mx); seg[now].mi = min(seg[seg[now].L].mi, seg[seg[now].R].mi); return now; } void update(int pos, int val, int L, int R, int cur) { if (L == R) { seg[cur].mx = seg[cur].mi = seg[cur].sum = val; return; } int mid = (L + R) >> 1; if (pos <= mid) { update(pos, val, L, mid, seg[cur].L); } else update(pos, val, mid + 1, R, seg[cur].R); int lson = seg[cur].L, rson = seg[cur].R; seg[cur].mx = max(seg[lson].mx, seg[rson].mx); seg[cur].mi = min(seg[lson].mi, seg[rson].mi); seg[cur].sum = seg[lson].sum + seg[rson].sum; } vector<long long int> ask(int be, int en, int L, int R, int cur) { // cout << "now" << endl; // cout << L << " " << R << endl; if (L >= be && R <= en) { vector<long long int> vc; vc.push_back(seg[cur].sum); vc.push_back(seg[cur].mx); vc.push_back(seg[cur].mi); return vc; } // cout << L << " " << R << endl; int mid = (L + R) >> 1; vector<long long int> ans; for (int i = 0; i < 3; ++i) ans.push_back(0); ans[1] = -inf; ans[2] = inf; if (be <= mid) { vector<long long int> res = ask(be, en, L, mid, seg[cur].L); // cout << "left" << " " << L << " " << R << endl; // for (int i = 0; i < 3; ++i) { // cout << res[i] << " "; // } // cout << endl; ans[0] += res[0]; ans[1] = max(ans[1], res[1]); ans[2] = min(ans[2], res[2]); } if (en >= mid + 1) { vector<long long int> res = ask(be, en, mid + 1, R, seg[cur].R); // cout << "right" << " " << L << " " << R << endl; // for (int i = 0; i < 3; ++i) { // cout << res[i] << " "; // } // cout << endl; // cout << "vimi" << " " << L << " " << R << endl; // for (int i = 0; i < 3; ++i) { // cout << ans[i] << " "; // } // cout << endl; ans[0] += res[0]; ans[1] = max(ans[1], res[1]); ans[2] = min(ans[2], res[2]); } return ans; } void work() { int n; scanf("%d", &n); build(1, n); int q; scanf("%d", &q); while (q--) { int op, one, two; scanf("%d%d%d", &op, &one, &two); if (op == 0) { update(one, two, 1, n, 1); } else { vector<long long int> vc = ask(one, two, 1, n, 1); // cout << "test " << vc[0] << " " << vc[1] << " " << vc[2] << endl; printf("%lld ", vc[0] - vc[1] - vc[2]); } } } int main() { // freopen("data.txt", "r", stdin); work(); return 0; }
改了一改就行了
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 2; const long long int inf = (long long int) 1e18; const int oo = (int) 1e9; struct segTree { int L, R; long long int sum; int mx, mi; } seg[maxn << 3]; int root; int build(int L, int R) { int now = ++root; if (L == R) { seg[now].sum = seg[now].mi = seg[now].mx = 0; return now; } int mid = (L + R) >> 1; seg[now].L = build(L, mid); seg[now].R = build(mid + 1, R); seg[now].sum = seg[seg[now].L].sum + seg[seg[now].R].sum; seg[now].mx = max(seg[seg[now].L].mx, seg[seg[now].R].mx); seg[now].mi = min(seg[seg[now].L].mi, seg[seg[now].R].mi); return now; } void update(int pos, int val, int L, int R, int cur) { if (L == R) { seg[cur].mx = seg[cur].mi = seg[cur].sum = val; return; } int mid = (L + R) >> 1; if (pos <= mid) { update(pos, val, L, mid, seg[cur].L); } else update(pos, val, mid + 1, R, seg[cur].R); int lson = seg[cur].L, rson = seg[cur].R; seg[cur].mx = max(seg[lson].mx, seg[rson].mx); seg[cur].mi = min(seg[lson].mi, seg[rson].mi); seg[cur].sum = seg[lson].sum + seg[rson].sum; } void ask(int be, int en, int L, int R, long long int &sum, int &mx, int &mi, int cur) { if (L >= be && R <= en) { sum += seg[cur].sum; mx = max(seg[cur].mx, mx); mi = min(seg[cur].mi, mi); return; } int mid = (L + R) >> 1; if (be <= mid) { ask(be, en, L, mid, sum, mx, mi, seg[cur].L); } if (en >= mid + 1) { ask(be, en, mid + 1, R, sum, mx, mi, seg[cur].R); } } void work() { int n; scanf("%d", &n); build(1, n); int q; scanf("%d", &q); while (q--) { int op, one, two; scanf("%d%d%d", &op, &one, &two); if (op == 0) { update(one, two, 1, n, 1); } else { long long int sum = 0; int mx = -oo; int mi = oo; ask(one, two, 1, n, sum, mx, mi, 1); printf("%lld ", sum - mx - mi); } } } int main() { // freopen("data.txt", "r", stdin); work(); return 0; }
http://codeforces.com/contest/984/problem/D
画图,然后变成简单的区间DP
#include <bits/stdc++.h> using namespace std; const int maxn = 5e3 + 20; int dp[maxn][maxn]; int f[maxn][maxn]; int a[maxn]; int dfs(int be, int en) { if (be > en) { assert(false); } if (be == en) return dp[be][en] = f[be][en] = a[be]; if (f[be][en] != -1) return f[be][en]; int left = dfs(be, en - 1); int right = dfs(be + 1, en); f[be][en] = left ^ right; dp[be][en] = max(dp[be + 1][en], max(dp[be][en - 1], left ^ right)); return f[be][en]; } void work() { int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { f[i][j] = dp[i][j] = -1; } } for (int i = 1; i <= n; ++i) { scanf("%d", a + i); } int q; scanf("%d", &q); while (q--) { int L, R; scanf("%d%d", &L, &R); // cout << L << " " << R << endl; dfs(L, R); printf("%d ", dp[L][R]); } } int main() { // freopen("data.txt", "r", stdin); work(); return 0; }
韩罗塔
#include <cstdio> #include <cstdlib> #include <stack> void move(int val, char from, char broow, char to) { printf("%d from %c broow %c to %c ", val, from, broow, to); } int step; void dfs(int n, char a, char b, char c) { if (n == 0) return; step++; if (n == 1) { move(n, a, ' ', b); return; } dfs(n - 1, a, c, b); move(n, a, ' ', b); dfs(n - 1, c, b, a); } void work() { int n = 5; dfs(n, 'A', 'B', 'C'); printf("%d ", step); } int main() { work(); return 0; }
光明小学的小朋友们要举行一年一度的接力跑大赛了,但是小朋友们却遇到了一个难题:设计接力跑大赛的线路,你能帮助他们完成这项工作么?
光明小学可以抽象成一张有N个节点的图,每两点间都有一条道路相连。光明小学的每个班都有M个学生,所以你要为他们设计出一条恰好经过M条边的路径。
光明小学的小朋友们希望全盘考虑所有的因素,所以你需要把任意两点间经过M条边的最短路径的距离输出出来以供参考。
你需要设计这样一个函数:
res[][] Solve( N, M, map[][]);
注意:map必然是N * N的二维数组,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。(道路全部是无向边,无自环)2 <= N <= 100, 2 <= M <= 1e6。要求时间复杂度控制在O(N^3*log(M))。
map数组表示了一张稠密图,其中任意两个不同节点i,j间都有一条边,边的长度为map[i][j]。N表示其中的节点数。
你要返回的数组也必然是一个N * N的二维数组,表示从i出发走到j,经过M条边的最短路径
你的路径中应考虑包含重复边的情况。
/* * @Author: vimiliu * @Date: 2018-07-18 15:18:42 * @Last Modified by: vimiliu * @Last Modified time: 2018-07-18 20:22:43 */ #include <bits/stdc++.h> using namespace std; const int maxn = 200 + 2; struct Matrix { int a[maxn][maxn]; int col, row; void init() { for (int i = 1; i <= row; ++i) { for (int j = 1; j <= col; ++j) { a[i][j] = -1; // can not go } } } }; void show(struct Matrix a) { for (int i = 1; i <= a.row; ++i) { for (int j = 1; j <= a.col; ++j) { cout << a.a[i][j] << " "; } cout << endl; } cout << "debug ------ " << endl; } struct Matrix MatrixMul(struct Matrix a, struct Matrix b) { struct Matrix res; res.row = a.row; //行等于第一个矩阵的行 res.col = b.col; //列等于第二个矩阵的列 for (int i = 1; i <= a.row; ++i) { for (int j = 1; j <= a.col; ++j) { int val = -1; // can not go for (int k = 1; k <= b.row; ++k) { if (a.a[i][k] == -1 || b.a[k][j] == -1) continue; if (val == -1) val = a.a[i][k] + b.a[k][j]; else val = min(val, a.a[i][k] + b.a[k][j]); } res.a[i][j] = val; } } return res; } struct Matrix MatrixQuickPow(struct Matrix a, struct Matrix b, int n) { while (n > 0) { if (n & 1) { a = MatrixMul(a, b); } b = MatrixMul(b, b); n >>= 1; } return a; } int e[maxn][maxn]; int n; void inputData() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { scanf("%d", &e[i][j]); if (e[i][j] == 0) e[i][j] = -1; } } } void work() { struct Matrix I; I.row = I.col = n; I.init(); for (int i = 1; i <= n; ++i) { I.a[i][i] = 0; } struct Matrix b; b.row = b.col = n; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { b.a[i][j] = e[i][j]; } } // input data /////////////////////////// int m = 2; struct Matrix ans = MatrixQuickPow(I, b, m); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { printf("%d ", ans.a[i][j]); } printf(" "); } } int main() { freopen("data.txt", "r", stdin); inputData(); work(); return 0; }