Codeforces Round #344 (Div. 2)
注意是或不是异或
#include <bits/stdc++.h> int a[1005], b[1005]; int main() { int n; scanf ("%d", &n); for (int i=0; i<n; ++i) { scanf ("%d", a+i); } for (int i=0; i<n; ++i) { scanf ("%d", b+i); } int ans = 0; for (int i=0; i<n; ++i) { int x = 0, y = 0; for (int j=i; j<n; ++j) { x |= a[j]; y |= b[j]; ans = std::max (ans, x + y); } } printf ("%d\n", ans); return 0; }
color[i][j] = max (timei(rowi), timej(colj)))
#include <bits/stdc++.h> const int N = 5e3 + 5; int a[N][N]; std::pair<int, int> row[N], col[N]; int main() { int n, m, k; scanf ("%d%d%d", &n, &m, &k); for (int op, x, y, i=1; i<=k; ++i) { scanf ("%d%d%d", &op, &x, &y); if (op == 1) { row[x] = std::make_pair (y, i); } else { col[x] = std::make_pair (y, i); } } for (int i=1; i<=n; ++i) { for (int j=1; j<=m; ++j) { int tr = row[i].second, tc = col[j].second; if (tr > tc && tr > 0) { a[i][j] = row[i].first; } else if (tc > tr && tc > 0) { a[i][j] = col[j].first; } } } for (int i=1; i<=n; ++i) { for (int j=1; j<=m; ++j) { printf ("%d%c", a[i][j], j == m ? '\n' : ' '); } } return 0; }
单调队列+排序 C - Report
题意:给m次操作,每次操作使得[1, r]范围的的a[i]升序或降序排序,问a[i]最后的结果
分析:因为左端点固定,右端点远的且操作时间靠后的可以覆盖之前右端点近的操作,所以先从右端点最远且时间靠后的时间出发,之后类似只要处理右端点降序的位置,即维护一个单调队列。队列中后一次操作长度不大于前一次长度,减少的长度k里的数字为前一次范围中前k大的数或前k小的数。
#include <bits/stdc++.h> const int N = 2e5 + 5; int a[N], b[N]; int r[N], t[N]; int main() { int n, m; scanf ("%d%d", &n, &m); for (int i=1; i<=n; ++i) { scanf ("%d", a+i); } int s = 0; for (int x, y, i=1; i<=m; ++i) { scanf ("%d%d", &x, &y); while (s > 0 && y >= r[s-1]) s--; t[s] = x; r[s] = y; s++; } r[s++] = 0; int bl = 1, br = r[0]; for (int i=bl; i<=br; ++i) b[i] = a[i]; std::sort (b+1, b+1+br); for (int i=1; i<s; ++i) { for (int j=r[i-1]; j>r[i]; --j) { a[j] = (t[i-1] == 1) ? b[br--] : b[bl++]; } } for (int i=1; i<=n; ++i) { printf ("%d ", a[i]); } puts (""); return 0; }
KMP D - Messenger
题意:给两个字符串,问后者在前者里出现的次数。给出的方式:1-a 2-b 3-c 4-d(abbcccddd)
分析:其实想明白就知道这就是简单的KMP问题,文本串第一个和最后一个的个数一定要比模式串多,且里面的要完全相等。还要考虑特殊情况,压缩后m==1或2时。
#include <bits/stdc++.h> typedef long long ll; const int N = 2e5 + 5; struct Part { ll len; char ch; bool operator == (const Part &rhs) const { return len == rhs.len && ch == rhs.ch; } bool operator >= (const Part &rhs) const { return len >= rhs.len && ch == rhs.ch; } bool operator != (const Part &rhs) const { return len != rhs.len || ch != rhs.ch; } }; Part A[N], B[N]; int fail[N]; int compress(Part *C, int n) { int m = 0; for (int i=1; i<n; ++i) { if (C[m].ch == C[i].ch) { C[m].len += C[i].len; } else { C[++m] = C[i]; } } return m + 1; } void get_fail(Part *P, int lenp) { int i = 0, j = -1; fail[0] = -1; while (i < lenp) { if (j == -1 || P[j] == P[i]) { ++i; ++j; fail[i] = j; } else { j = fail[j]; } } } ll KMP(Part *C, int n, Part *D, int m) { get_fail (D, m); int i = 0, j = 0; ll ret = 0; while (i < n) { while (j != -1 && C[i] != D[j]) j = fail[j]; i++; j++; if (j == m) { if (C[i] >= D[m] && C[i-m-1] >= D[-1]) ret++; j = fail[j]; } } return ret; } int main() { int n, m; scanf ("%d%d", &n, &m); int bug = 0; char str[3]; for (int i=0; i<n; ++i) { scanf ("%I64d-%s", &A[i].len, str); A[i].ch = str[0]; } for (int i=0; i<m; ++i) { scanf ("%I64d-%s", &B[i].len, str); B[i].ch = str[0]; } n = compress (A, n); m = compress (B, m); ll ans = 0; if (m == 1) { for (int i=0; i<n; ++i) { if (A[i].ch == B[0].ch) { ans += std::max (0ll, A[i].len - B[0].len + 1); } } } else if (m == 2) { for (int i=0; i<n-1; ++i) { if (A[i] >= B[0] && A[i+1] >= B[1]) ans++; } } else { ans = KMP (A+1, n-2, B+1, m-2); } printf ("%I64d\n", ans); return 0; }
题意:将一个点移动到另一个点(可相同),求
分析:推算化简的得到:
或者
先考虑后者,再次化简得到:,,可以抽象成ax+b, (x = ar),所以我们枚举ar,得到最大的,用到了凸包,把直线加入凸包,得到单调上升的类似于这样的,然后二分找最大值。前者类似。
第一次碰到这种题,写详细点:)
#include <bits/stdc++.h> typedef long long ll; const int N = 2e5 + 5; int a[N]; ll sum[N]; struct Line { int a; ll b; ll get(int x) { return 1ll * a * x + b; } }; struct Convex_hull { int sz; Line *hull; Convex_hull(int maxn) { hull = new Line[++maxn]; sz = 0; } void clear() { sz = 0; } bool is_bad(int cur, int pre, int nex) { Line c = hull[cur], p = hull[pre], n = hull[nex]; return (c.b - n.b) * (c.a - p.a) <= (p.b - c.b) * (n.a - c.a); } void add_line(int a, ll b) { hull[sz++] = (Line) {a, b}; while (sz > 2 && is_bad (sz-2, sz-3, sz-1)) { hull[sz-2] = hull[sz-1]; sz--; } } ll query(int x) { int low = -1, high = sz - 1; while (low + 1 < high) { int mid = low + high >> 1; if (hull[mid].get (x) <= hull[mid+1].get (x)) { low = mid; } else { high = mid; } } return hull[high].get (x); } }; int main() { int n; scanf ("%d", &n); ll ans = 0; sum[0] = 0; for (int i=1; i<=n; ++i) { scanf ("%d", a+i); sum[i] = sum[i-1] + a[i]; ans += 1ll * a[i] * i; } Convex_hull *hull = new Convex_hull (n); ll add = 0; for (int r=2; r<=n; ++r) { hull->add_line (r-1, -sum[r-2]); add = std::max (add, hull->query (a[r]) + sum[r-1] - 1ll * a[r] * r); } hull->clear (); for (int l=n-1; l>=1; --l) { hull->add_line (-(l+1), -sum[l+1]); add = std::max (add, hull->query (-a[l]) + sum[l] - 1ll * a[l] * l); } printf ("%I64d\n", ans + add); return 0; }
编译人生,运行世界!