今天无意间找到了训练指南的网上代码,都是刘汝佳写的,在这。
今天在做这题1400 - "Ray, Pass me the dishes!",我写的线段树的思路跟上次的Frequent Sequence的思路类似,维护区间上从左端点开始、从右端点开始,中间部分的最优序列,查了半天,没查到问题,先把代码备份上来。
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 500005; typedef long long int64; int dish[MAXN]; int64 dish_sum[MAXN]; int64 get_sum(int L, int R) { return dish_sum[R] - dish_sum[L - 1]; } class SegNode { public: int L, R; int L_end, R_beg; int beg, end; int64 LR_sum() { return get_sum(L, R); } int64 L_sum() { return get_sum(L, L_end); } int64 R_sum() { return get_sum(R_beg, R); } int64 sum() { return get_sum(beg, end); } void log() { printf("[%d %d]: (%d %d), (%d %d), (%d %d).\n", L, R, L, L_end, R_beg, R, beg, end); } } node[5 * MAXN]; class SegTree { public: void build(int r, int L, int R) { node[r].L = L; node[r].R = R; if (L == R) { // leaf node[r].L_end = R; node[r].R_beg = L; node[r].beg = L; node[r].end = R; } else { // non leaf int M = (L + R) / 2; build(2 * r, L, M); build(2 * r + 1, M + 1, R); // left node[r].L_end = node[2 * r].L_end; if (node[2 * r].LR_sum() + node[2 * r + 1].L_sum() > node[2 * r].L_sum()) { node[r].L_end = node[2 * r + 1].L_end; } // right node[r].R_beg = node[2 * r + 1].R_beg; if (node[2 * r + 1].LR_sum() + node[2 * r].R_sum() > node[2 * r + 1].R_sum()) { node[r].R_beg = node[2 * r].R_beg; } // mid if (node[2 * r].sum() >= node[2 * r + 1].sum()) { node[r].beg = node[2 * r].beg; node[r].end = node[2 * r].end; } else { node[r].beg = node[2 * r + 1].beg; node[r].end = node[2 * r + 1].end; } if (node[2 * r].R_sum() + node[2 * r + 1].L_sum() > node[r].sum()) { node[r].beg = node[2 * r].R_beg; node[r].end = node[2 * r + 1].L_end; } } //node[r].log(); } void query(int r, int L, int R, int& left, int& right, int k) { if (L <= node[r].L && node[r].R <= R) { if (k == 0) { left = node[r].L; right = node[r].L_end; } else if (k == 1) { left = node[r].R_beg; right = node[r].R; } else { left = node[r].beg; right = node[r].end; } } else { if (R <= node[2 * r].R) { query(2 * r, L, R, left, right, k); } else if (L >= node[2 * r + 1].L) { query(2 * r + 1, L, R, left, right, k); } else { int left_beg, left_end, right_beg, right_end; query(2 * r, L, R, left_beg, left_end, k); query(2 * r + 1, L, R, right_beg, right_end, k); if (k == 0) { left = left_beg; right = left_end; if (get_sum(left_beg, right_end) > get_sum(left, right)) { left = left_beg; right = right_end; } } else if (k == 1) { left = right_beg; right = right_end; if (get_sum(left_beg, right_end) > get_sum(left, right)) { left = left_beg; right = right_end; } } else { if (get_sum(left_beg, left_end) >= get_sum(right_beg, right_end)) { left = left_beg; right = left_end; } else { left = right_beg; right = right_end; } int m_l, m_r, x; query(2 * r, L, R, m_l, x, 1); query(2 * r + 1, L, R, x, m_r, 0); if (get_sum(m_l, m_r) > get_sum(left, right)) { left = m_l; right = m_r; } } } } } } tree; int main() { int n, m, c = 0; while (scanf("%d%d", &n, &m) != EOF) { dish_sum[0] = 0; for (int i = 1; i <= n; i++) { scanf("%d", &dish[i]); dish_sum[i] = dish_sum[i - 1] + dish[i]; } tree.build(1, 1, n); printf("Case %d:\n", ++c); for (int i = 0; i < m; i++) { int l, r, left, right; scanf("%d%d", &l, &r); if (l > r) swap(l, r); l = max(1, l); r = min(n, r); tree.query(1, l, r, left, right, 2); printf("%d %d\n", left, right); } } }