zoukankan      html  css  js  c++  java
  • 最大字段和--GSS1 MUSHROOM ORZ

    过于naive了= =作为一个知识点总结一下算了。主要就是合并。对于一个区间的最大字段和,可以分别事下面的两个区间的子段和,或者事左边的右边加右边的左边。然后搞一下 = =

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    typedef long long ll;
    const ll maxn = 3000100;
    
    ll lson[maxn], rson[maxn], lm[maxn], rm[maxn], mans[maxn], sum[maxn];
    ll ne = 0, root;
    
    ll build(ll l, ll r) {
        ll now = ++ ne;
        if(l ^ r) {
            ll mid = (l + r) >> 1;
            lson[now] = build(l, mid);
            rson[now] = build(mid + 1, r);
        }
        return now;
    }
    
    void update(ll now) {
        if(lson[now]) {
            sum[now] = sum[lson[now]] + sum[rson[now]];
            lm[now] = max(lm[lson[now]], sum[lson[now]] + lm[rson[now]]);
            rm[now] = max(rm[rson[now]], sum[rson[now]] + rm[lson[now]]);
            mans[now] = max(max(mans[lson[now]], mans[rson[now]]), lm[rson[now]] + rm[lson[now]]);
        }
    }
    
    void insert(ll now, ll l, ll r, ll v, ll pos) {
        if(l == r) {
            sum[now] = lm[now] = rm[now] = mans[now] = v;
        }
        else {
            ll mid = (l + r) >> 1;
            if(pos <= mid) insert(lson[now], l, mid, v, pos);
            else insert(rson[now], mid + 1, r, v, pos);
            update(now);
        }
    }
    
    ll ask(ll now, ll l, ll r, ll ls, ll rs) {
        ll ret;
        if(l == ls && r == rs) ret = now;
        else {
            ll mid = (l + r) >> 1;
            if(rs <= mid) ret = ask(lson[now], l, mid ,ls, rs);
            else if(ls >= mid + 1) ret = ask(rson[now], mid + 1, r, ls, rs);
            else {
                ret = ++ ne;
                ll rl = ask(lson[now], l, mid, ls, mid);
                ll rr = ask(rson[now], mid + 1, r, mid + 1, rs);
                lson[ret] = rl, rson[ret] = rr;
                update(ret);
            }
        }
        return ret;
    }
    
    ll ll_get() {
        ll x = 0; char c = (char)getchar(); bool flag = 0;
        while(!isdigit(c) && c != '-') c = (char)getchar();
        if(c == '-') flag = 1;
        while(!isdigit(c)) c = (char)getchar();
        while(isdigit(c)) {
            x = x * 10 + (ll)(c - '0');
            c = (char)getchar();
        }
        if(flag) x = -x;
        return x;
    }
    
    ll n, m;
    
    void sov() {
        n = ll_get(); root = build(1, n);
        for(ll i = 1; i <= n; ++ i) {
            ll a = ll_get();
            insert(root, 1, n, a, i);
        }
        m = ll_get();
        while(m --) {
            ll ls, rs; ls = ll_get(), rs = ll_get();
            ll ans = ask(root, 1, n, ls, rs);
            printf("%lld
    ", mans[ans]);
        }
    }
    
    int main() {
        //freopen("test.in", "r", stdin);
        //freopen("b.out", "w", stdout);
        sov();
        return 0;
    }
  • 相关阅读:
    分布图
    针对回归训练卷积神经网络
    polyfit 多项式曲线拟合matlab
    Re-run failed tests in testng
    URI 和 URL的区别
    十分钟理解Gradle
    移动App测试实战—专项测试(转)
    adb 常用命令
    MySQL基本操作
    Java注解
  • 原文地址:https://www.cnblogs.com/ianaesthetic/p/3988806.html
Copyright © 2011-2022 走看看