UVa-1400 - "Ray, Pass me the dishes!"
2013-05-17 23:30
344 查看
题目大意:
已知一个数列。每次询问x、y,求在区间 [x,y] 中,数字和最大的段i、j
分析:
线段数。分别记录前缀和最大,后缀和最大,以及区间和最大的位置即可程序:
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; #define LL long long const int Max_N = 1000010; int n_num, n_req; LL num[Max_N], sum[Max_N]; typedef pair<int, int> Interval; inline LL Sum(int x, int y) { return sum[y] - sum[x - 1]; } inline LL Sum(Interval x) { return Sum(x.first, x.second); } inline Interval Better(Interval x, Interval y) { if(Sum(x) == Sum(y)) return x < y ? x : y; else return Sum(x) < Sum(y) ? y : x; } struct Interval_Tree { int max_suffix[Max_N]; int max_prefix[Max_N]; Interval max_sub[Max_N]; void Build(int root, int l, int r) { if(l == r) { max_suffix[root] = max_prefix[root] = l; max_sub[root] = make_pair(l, l); } else { int mid = (l + r) >> 1; int lc = root << 1; int rc = (root << 1) | 1; Build(lc, l, mid); Build(rc, mid + 1, r); LL v1 = Sum(l, max_prefix[lc]); LL v2 = Sum(l, max_prefix[rc]); if(v1 == v2) max_prefix[root] = min(max_prefix[lc], max_prefix[rc]); else max_prefix[root] = v1 > v2 ? max_prefix[lc] : max_prefix[rc]; v1 = Sum(max_suffix[lc], r); v2 = Sum(max_suffix[rc], r); if(v1 == v2) max_suffix[root] = min(max_suffix[lc], max_suffix[rc]); else max_suffix[root] = v1 > v2 ? max_suffix[lc] : max_suffix[rc]; max_sub[root] = Better(max_sub[lc], max_sub[rc]); max_sub[root] = Better(max_sub[root], make_pair(max_suffix[lc], max_prefix[rc])); } } Interval Query_Suffix(int root, int l, int r, int x) { if(max_suffix[root] >= x) return make_pair(max_suffix[root], r); int mid = (l + r) >> 1; int lc = root << 1; int rc = (root << 1) | 1; if(mid + 1 <= x) return Query_Suffix(rc, mid + 1, r, x); else { Interval ret = Query_Suffix(lc, l, mid, x); ret.second = r; return Better(ret, make_pair(max_suffix[rc], r)); } } Interval Query_Prefix(int root, int l, int r, int y) { if(max_prefix[root] <= y) return make_pair(l, max_prefix[root]); int mid = (l + r) >> 1; int lc = root << 1; int rc = (root << 1) | 1; if(mid >= y) return Query_Prefix(lc, l, mid, y); else { Interval ret = Query_Prefix(rc, mid + 1, r, y); ret.first = l; return Better(ret, make_pair(l, max_prefix[lc])); } } Interval Query(int root, int l, int r, int x, int y) { if(x <= l && y >= r) return max_sub[root]; int mid = (l + r) >> 1; int lc = root << 1; int rc = (root << 1) | 1; if(y <= mid) return Query(lc, l, mid, x, y); if(x >= mid + 1) return Query(rc, mid + 1, r, x, y); Interval ret1 = Query_Suffix(lc, l, mid, x); Interval ret2 = Query_Prefix(rc, mid + 1, r, y); Interval ret3 = Better(Query(lc, l, mid, x, y), Query(rc, mid + 1, r, x, y)); return Better(ret3, make_pair(ret1.first, ret2.second)); } }tree; void Init() { sum[0] = 0; for(int i = 1; i <= n_num; i ++) { scanf("%lld", &num[i]); sum[i] = sum[i - 1] + num[i]; } tree.Build(1, 1, n_num); } void Solve() { for(int i = 0; i < n_req; i ++) { int x, y; scanf("%d%d", &x, &y); Interval ret = tree.Query(1, 1, n_num, x, y); printf("%d %d\n", ret.first, ret.second); } } int main() { int cnt = 0; while(scanf("%d%d", &n_num, &n_req) == 2) { printf("Case %d:\n", ++ cnt); Init(); Solve(); } return 0; }
相关文章推荐
- UVa 1400 "Ray, Pass me the dishes!"(线段树)
- uva 1400 "Ray, Pass me the dishes!" 线段树
- UVA 1400 "Ray, Pass me the dishes!" (线段树)
- uva 1400 - "Ray, Pass me the dishes!"(线段树)
- UVA 1400 1400 - "Ray, Pass me the dishes!"(线段树)
- Uva 1400 "Ray, Pass me the dishes!" (线段树 区间合并)
- UVA 1400 1400 - "Ray, Pass me the dishes!"(线段树)
- uva1400 "Ray, Pass me the dishes!"
- UVA-1400-"Ray, Pass me the dishes!"(线段树-区间合并)
- UVA1400 - "Ray, Pass me the dishes!"
- UVa 1400 "Ray, Pass me the dishes!"(区间最大连续数组和)
- UVa 1400 (线段树) "Ray, Pass me the dishes!"
- UVA1400 "Ray, Pass me the dishes!" 线段树
- uva 1400 "Ray, Pass me the dishes!"
- uva 1400 - "Ray, Pass me the dishes!"
- UVA 1400 "Ray, Pass me the dishes!"(线段树)
- 1400 - "Ray, Pass me the dishes!"
- 线段树(1):点修改 (uva 1400 Ray,Pass me the Dishes)
- UVALive - 3938 "Ray, Pass me the dishes!" 线段树
- UVALive - 3938 "Ray, Pass me the dishes!" 线段树单点更新