UVA 1400 - "Ray, Pass me the dishes!"
题意:给定一个序列,每次询问一个[L,R]区间,求出这个区间的最大连续子序列和
思路:线段树,每个节点维护3个值,最大连续子序列,最大连续前缀序列,最大连续后缀序列,那么每次pushup的时候,根据这3个序列去拼凑得到新的一个结点即可
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson(x) ((x<<1) + 1) #define rson(x) ((x<<1) + 2) #define MP(a, b) make_pair(a, b) typedef long long ll; typedef pair<int, int> Point; const int N = 500005; int n, m; ll a[N], sum[N]; struct Node { int l, r; int prex, sufx; Point sub; } node[4 * N]; ll get(Point x) { return sum[x.second] - sum[x.first - 1]; } bool Max(Point a, Point b) { long long sa = get(a); long long sb = get(b); if (sa != sb) return sa > sb; return a < b; } Point Maxsub(Node a, Node b) { Point ans; if (Max(a.sub, b.sub)) ans = a.sub; else ans = b.sub; if (Max(MP(a.sufx, b.prex), ans)) ans = MP(a.sufx, b.prex); return ans; } int Maxpre(Node a, Node b) { Point ans = MP(a.l, a.prex); if (Max(MP(a.l, b.prex), ans)) ans = MP(a.l, b.prex); return ans.second; } int Maxsuf(Node a, Node b) { Point ans = MP(b.sufx, b.r); if (Max(MP(a.sufx, b.r), ans)) ans = MP(a.sufx, b.r); return ans.first; } Node pushup(Node a, Node b) { Node ans; ans.l = a.l; ans.r = b.r; ans.sub = Maxsub(a, b); ans.prex = Maxpre(a, b); ans.sufx = Maxsuf(a, b); return ans; } void build(int l, int r, int x) { if (l == r) { node[x].l = l; node[x].r = r; node[x].prex = node[x].sufx = l; node[x].sub = MP(l, l); return ; } int mid = (l + r) / 2; build(l, mid, lson(x)); build(mid + 1, r, rson(x)); node[x] = pushup(node[lson(x)], node[rson(x)]); } Node Query(int l, int r, int x) { if (l <= node[x].l && r >= node[x].r) return node[x]; int mid = (node[x].l + node[x].r) / 2; Node ans; if (l <= mid && r > mid) ans = pushup(Query(l, r, lson(x)), Query(l, r, rson(x))); else if (l <= mid) ans = Query(l, r, lson(x)); else if (r > mid) ans = Query(l, r, rson(x)); return ans; } int main() { int cas = 0; while (~scanf("%d%d", &n, &m)) { for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); sum[i] = sum[i - 1] + a[i]; } build(1, n, 0); printf("Case %d:\n", ++cas); int a, b; while (m--) { scanf("%d%d", &a, &b); Node ans = Query(a, b, 0); printf("%d %d\n", ans.sub.first, ans.sub.second); } } return 0; }
UVA 1400 1400 - "Ray, Pass me the dishes!"(线段树)
时间: 2024-10-21 00:05:13