题意: 求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 << 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<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; }
// // 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 << 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; }