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

来源:互联网 发布:google 高程提取软件 编辑:程序博客网 时间:2024/05/29 19:23

题意: 求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 <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <set>#include <vector>using namespace std;#define pr(x) cout << #x << " = " << x << "  "#define prln(x) cout << #x << " = " << x << endlconst 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 | 1typedef pair<int, int> 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 <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <set>#include <vector>using namespace std;#define pr(x) cout << #x << " = " << x << "  "#define prln(x) cout << #x << " = " << x << endlconst 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 | 1typedef 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;}


0 0
原创粉丝点击