UVALive 3938 Ray, Pass me the dishes (线段树区间合并)

题意: 求q次询问的静态区间连续最大和起始位置和终止位置 输出字典序最小的解

分析: 很显然的区间合并的题目啦

          常理就是维护pre, sub, suf 最大的 前缀和, 连续和, 后缀和 然后这个题还要记录解的位置所以还要区间总和sum

          然后解的位置preR, subL, subR, sufL 然后更新就好了 自己注意下字典序就好了 建树和查询都类似

总结: 死守着HH线段树风格 导致代码丑的飞起 不会变通 以及思路清晰 抽象函数的重要性 

          反正呢 多刷题多总结吧 偶尔用用结构体的 还是对于某些题的解题代码减少不错的 比如说本题

优美版: 参考之后100行左右

//
//  Created by TaoSama on 2015-09-15
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

typedef long long LL;

int n, q;
LL a[N];

#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

typedef pair Interval;

struct Node {
    int l, r;
    int preR, sufL;
    Interval sub;
} dat[N << 2];

LL sum(Interval x) {
    return a[x.second] - a[x.first - 1];
}

Interval getMax(Interval x, Interval y) {
    LL sx = sum(x), sy = sum(y);
    if(sx != sy) return sx > sy ? x : y;
    return x < y ? x : y;
}

Node push_up(Node x, Node y) {
    Node ret;
    ret.l = x.l; ret.r = y.r;
    ret.preR = getMax(Interval(x.l, x.preR), Interval(x.l, y.preR)).second;
    ret.sufL = getMax(Interval(y.sufL, y.r), Interval(x.sufL, y.r)).first;
    ret.sub = getMax(Interval(x.sufL, y.preR), getMax(x.sub, y.sub));
    return ret;
}

void build(int l, int r, int rt) {
    if(l == r) {
        dat[rt].l = dat[rt].r = l;
        dat[rt].preR = dat[rt].sufL = l;
        dat[rt].sub = Interval(l, l);
        return;
    }
    int m = l + r >> 1;
    build(lson);
    build(rson);
    dat[rt] = push_up(dat[rt << 1], dat[rt << 1 | 1]);
}

Node query(int L, int R, int rt) {
    if(L <= dat[rt].l && dat[rt].r <= R) return dat[rt];
    int m = dat[rt].l + dat[rt].r >> 1;

    Node ret;
    if(L <= m && R > m)
        ret = push_up(query(L, R, rt << 1), query(L, R, rt << 1 | 1));
    else if(L <= m) ret = query(L, R, rt << 1);
    else if(R > m) ret = query(L, R, rt << 1 | 1);
    return ret;
}

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    int kase = 0;
    while(scanf("%d%d", &n, &q) == 2) {
        for(int i = 1; i <= n; ++i) {
            int x; scanf("%d", &x);
            a[i] = a[i - 1] + x;
        }
        build(root);
        printf("Case %d:\n", ++kase);
        while(q--) {
            int l, r; scanf("%d%d", &l, &r);
            Interval ans = query(l, r, 1).sub;
            printf("%d %d\n", ans.first, ans.second);
        }
    }
    return 0;
}

我写的丑瞎了的版本: 200行左右

//
//  Created by TaoSama on 2015-09-15
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

typedef long long LL;

LL sum[N << 2], pre[N << 2], sub[N << 2], suf[N << 2];
int preR[N << 2], subL[N << 2], subR[N << 2], sufL[N << 2];

void push_up(int rt) {
    int ls = rt << 1, rs = rt << 1 | 1;
    sum[rt] = sum[ls] + sum[rs];
    LL Max, l, r;

    //prefix
    Max = pre[ls], r = preR[ls];
    if(pre[ls] < sum[ls] + pre[rs]) {
        Max = sum[ls] + pre[rs];
        r = preR[rs];
    }
    pre[rt] = Max, preR[rt] = r;
    //suffix
    Max = suf[rs], l = sufL[rs];
    if(suf[rs] <= sum[rs] + suf[ls]) {
        Max = sum[rs] + suf[ls];
        l = sufL[ls];
    }
    suf[rt] = Max, sufL[rt] = l;
    //sub
    Max = sub[ls], l = subL[ls], r = subR[ls];
    if(Max < suf[ls] + pre[rs]) {
        Max = suf[ls] + pre[rs];
        l = sufL[ls], r = preR[rs];
    }
    if(Max < sub[rs]) {
        Max = sub[rs];
        l = subL[rs], r = subR[rs];
    }
    sub[rt] = Max, subL[rt] = l, subR[rt] = r;
}

void build(int l, int r, int rt) {
    if(l == r) {
        scanf("%lld", &sum[rt]);
        pre[rt] = sub[rt] = suf[rt] = sum[rt];
        preR[rt] = subL[rt] = subR[rt] = sufL[rt] = l;
        return;
    }
    int m = l + r >> 1;
    build(lson);
    build(rson);
    push_up(rt);
}

struct Node {
    LL sum, pre, sub, suf;
    int preL, preR, subL, subR, sufL, sufR;
};

Node query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) {
        Node t;
        t.sum = sum[rt]; t.pre = pre[rt];
        t.sub = sub[rt]; t.suf = suf[rt];
        t.preL = l; t.preR = preR[rt];
        t.subL = subL[rt]; t.subR = subR[rt];
        t.sufL = sufL[rt]; t.sufR = r;
        return t;
    }
    int m = l + r >> 1, x = 0, y = 0;
    Node ll, rr, ret;
    if(L <= m) ll = query(L, R, lson), x = 1;
    if(R > m) rr = query(L, R, rson), y = 1;
    if(x && !y) ret = ll;
    else if(!x && y) ret = rr;
    else {
        ret.sum = ll.sum + rr.sum;
        //prefix
        ret.pre = ll.pre, ret.preL = ll.preL, ret.preR = ll.preR;
        if(ret.pre < ll.sum + rr.pre) {
            ret.pre = ll.sum + rr.pre;
            ret.preL = ll.preL; ret.preR = rr.preR;
        }
        //suffix
        ret.suf = rr.suf, ret.sufL = rr.sufL, ret.sufR = rr.sufR;
        if(ret.suf <= rr.sum + ll.suf) {
            ret.suf = rr.sum + ll.suf;
            ret.sufL = ll.sufL; ret.sufR = rr.sufR;
        }
        //sub
        ret.sub = ll.sub, ret.subL = ll.subL, ret.subR = ll.subR;
        if(ret.sub < ll.suf + rr.pre) {
            ret.sub = ll.suf + rr.pre;
            ret.subL = ll.sufL; ret.subR = rr.preR;
        }
        if(ret.sub < rr.sub) {
            ret.sub = rr.sub;
            ret.subL = rr.subL; ret.subR = rr.subR;
        }
    }
    return ret;
}

int n, q;

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    int kase = 0;
    while(scanf("%d%d", &n, &q) == 2) {
        build(root);
        printf("Case %d:\n", ++kase);
        while(q--) {
            int l, r; scanf("%d%d", &l, &r);
            Node ans = query(l, r, root);
            printf("%d %d\n", ans.subL, ans.subR);
        }
    }
    return 0;
}


你可能感兴趣的:(数据结构,-,线段树)