Trainning Guide的代码

今天无意间找到了训练指南的网上代码,都是刘汝佳写的,在

今天在做这题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);

        }

    }

}

 

你可能感兴趣的:(ide)