zoukankan      html  css  js  c++  java
  • 1400

    第一次做线段树题目,确实一点也不会,想了很久,首先是线段树怎么作用,每一步会产生什么影响。
    首先,线段树的每次更新都更新了什么,为什么要这么更新,尤其是更新的区间,虽说原理很简单,就是要么在左子树,
    要么在右子树,要么兼顾左右子树,所以如果是在左子树,那就查找左子树,否则右子树,或者左右子树都查找,再合并左右子树,
    这仅是对于查找而言的。那么建树是怎么回事呢,首先建树必然会包括所有情况,每种情况事实上的是在这个过程中不断更新,
    事实上就是符合每次区间[l, r]的查找罢了,就是特殊情况处理了,然后再从特殊情况中拼凑出非特殊情况就可以了
    #include <iostream>
    #include <stack>
    #include <queue>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <set>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    
    #define INF 0x7ffffffffffLL
    #define N 500010
    #define LL long long
    #define mod 95041567
    
    using namespace std;
    
    struct node{
        LL MAX, MAX_PREFIX, MAX_SUFFIX;
        int l, r, ll, rr;
    };
    
    LL sum[N];
    node G[N << 2];
    
    void pushup(int L, int R, int rt){
        int mid = (R - L) / 2 + L;
    
        G[rt].MAX_PREFIX = G[rt << 1].MAX_PREFIX, G[rt].ll = G[rt << 1].ll;
        if(G[rt].MAX_PREFIX < G[(rt << 1) | 1].MAX_PREFIX + sum[mid] - sum[L - 1]){
            G[rt].MAX_PREFIX = G[(rt << 1) | 1].MAX_PREFIX + sum[mid] - sum[L - 1];
            G[rt].ll = G[(rt << 1) | 1].ll;
        }
    
        G[rt].MAX_SUFFIX = G[(rt << 1) | 1].MAX_SUFFIX, G[rt].rr = G[(rt << 1) | 1].rr;
        if(G[rt].MAX_SUFFIX <= G[rt << 1].MAX_SUFFIX + sum[R] - sum[mid]){
            G[rt].MAX_SUFFIX = G[rt << 1].MAX_SUFFIX + sum[R] - sum[mid];
            G[rt].rr = G[rt << 1].rr;
        }
    
        G[rt].MAX = G[rt << 1].MAX, G[rt].l = G[rt << 1].l, G[rt].r = G[rt << 1].r;
        if(G[(rt << 1) | 1].MAX > G[rt].MAX){
            G[rt].MAX = G[(rt << 1) | 1].MAX; 
            G[rt].l = G[(rt << 1) | 1].l; 
            G[rt].r = G[(rt << 1) | 1].r;
        }
        if(G[rt].MAX < G[rt << 1].MAX_SUFFIX + G[(rt << 1) | 1].MAX_PREFIX){
            G[rt].MAX = G[rt << 1].MAX_SUFFIX + G[(rt << 1) | 1].MAX_PREFIX;
            G[rt].l = G[rt << 1].rr;
            G[rt].r = G[(rt << 1) | 1].ll;
        }
        else if(G[rt].MAX == G[rt << 1].MAX_SUFFIX + G[(rt << 1) | 1].MAX_PREFIX){
            if(G[rt].l > G[rt << 1].rr){
                G[rt].l = G[rt << 1].rr;
                G[rt].r = G[(rt << 1) | 1].ll;
            }
            else if(G[rt].l == G[rt << 1].rr && G[rt].r > G[(rt << 1) | 1].ll)
                G[rt].r = G[(rt << 1) | 1].ll;
        }
    }
    
    void build_tree(int L, int R, int rt){
        if(L == R){
            G[rt].l = G[rt].r = L;
            G[rt].ll = G[rt].rr = L;
            G[rt].MAX = G[rt].MAX_SUFFIX = G[rt].MAX_PREFIX = sum[L] - sum[L - 1];
            return;
        }
        int mid = (R - L) / 2 + L;
        build_tree(L, mid, rt << 1);
        build_tree(mid + 1, R, (rt << 1) | 1);
        pushup(L, R, rt);
    }
    
    node query(int L, int R, int rt, int l, int r){
        if(L == l && R == r) return G[rt];
        int mid = (R - L) / 2 + L;
        if(mid < l) return query(mid + 1, R, (rt << 1) | 1, l, r);
        if(r <= mid) return query(L, mid, rt << 1, l, r);
    
        node ln = query(L, mid, rt << 1, l, mid);
        node rn = query(mid + 1, R, (rt << 1) | 1, mid + 1, r);
        node v = ln;
        if(v.MAX < rn.MAX) v = rn;
        if(v.MAX < ln.MAX_SUFFIX + rn.MAX_PREFIX){
            v.MAX = ln.MAX_SUFFIX + rn.MAX_PREFIX;
            v.l = ln.rr;
            v.r = rn.ll;
        }
        else if(v.MAX == ln.MAX_SUFFIX + rn.MAX_PREFIX){
            if(v.l > ln.rr){
                v.l = ln.rr;
                v.r = rn.ll;
            }
            else if(v.l == ln.rr && v.r > rn.ll) v.r = rn.ll;
        }
    
        v.MAX_PREFIX = ln.MAX_PREFIX, v.ll = ln.ll;
        v.MAX_SUFFIX = rn.MAX_SUFFIX, v.rr = rn.rr;
    
        if(v.MAX_PREFIX < sum[mid] - sum[l - 1] + rn.MAX_PREFIX){
            v.MAX_PREFIX = sum[mid] - sum[l - 1] + rn.MAX_PREFIX;
            v.ll = rn.ll;
        }
    
        if(v.MAX_SUFFIX <= sum[r] - sum[mid] + ln.MAX_SUFFIX){
            v.MAX_SUFFIX = sum[r] - sum[mid] + ln.MAX_SUFFIX;
            v.rr = ln.rr;
        }
    
        return v;
    }
    int main()
    {
      //  freopen("in.txt","r",stdin);
        int m, n, t = 1;
        sum[0] = 0;
        while(scanf("%d %d", &n, &m) != EOF){
            for(int i = 1; i <= n; ++i){
                scanf("%lld", &sum[i]);
                sum[i] += sum[i - 1];
            }
            build_tree(1, n, 1);
            printf("Case %d:
    ", t++);
            int l, r;
            for(int i = 0; i < m; ++i){
                scanf("%d %d", &l, &r);
                node v = query(1, n, 1, l, r);
                printf("%d %d
    ", v.l, v.r);
            }
        }
        return 0;
    }


  • 相关阅读:
    Centos7重置Mysql 8.0.1 root 密码
    MysQL使用一高级应用(下)
    MysQL使用一高级应用(上)
    MysQL使用一查询
    MysQL使用一创建库与表
    OSI七层协议模型、TCP/IP四层模型学习笔记
    python-作用域和装饰器
    python-正则表达式RE
    python-高阶函数和闭包
    python-内置函数及捕获异常
  • 原文地址:https://www.cnblogs.com/riskyer/p/3356061.html
Copyright © 2011-2022 走看看