• 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).
    ",
                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:
    ", ++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
    ", left, right);
            }
        }
    }
  • 相关阅读:
    Spring配置文件命名空间
    JSTL之数字、日期格式化<fmt:formatNumber/>、<fmt:formatDate/>
    获取真实ip
    DES
    MD5
    手动导入maven包
    windows下redis主从复制设置
    linux系统上传图片读取权限设置
    linux系统项目查看进程
    linux上服务起的很慢解决方式
  • 原文地址:https://www.cnblogs.com/litstrong/p/3289307.html
Copyright © 2020-2023  润新知