uva 1400 Ray, Pass me the dishes!(线段树, 分治法求最大连续和)
2014-09-02 13:14
316 查看
参照RJ大大的代码写的。非常经典的一题!!!
有很多易错的地方。。
有很多易错的地方。。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <queue> #include <stack> #include <cassert> #include <algorithm> #include <cmath> #include <limits> #include <set> #include <time.h> #include <errno.h> using namespace std; #define MIN(a, b) a < b ? a : b #define MAX(a, b) a > b ? a : b #define F(i, n) for (int i=0;i<(n);++i) #define REP(i, s, t) for(int i=s;i<=t;++i) #define UREP(i, s, t) for(int i=s;i>=t;--i) #define REPOK(i, s, t, o) for(int i=s;i<=t && o;++i) #define MEM0(addr, size) memset(addr, 0, size) #define LBIT(x) x&-x #define PI 3.1415926535897932384626433832795 #define HALF_PI 1.5707963267948966192313216916398 #define eps 1e-15 #define MAXN 500000 #define MAXM 1000 #define MOD 20071027 typedef long long LL; const double maxdouble = numeric_limits<double>::max(); const int INF = 0x7FFFFFFF; typedef pair<int,int> Interval; LL prefix_sum[MAXN + 10]; LL sum(int L, int R) { return prefix_sum[R] - prefix_sum[L-1]; } LL sum(Interval p) { return sum(p.first, p.second); } Interval better(Interval a, Interval b) { if(sum(a) != sum(b)) return sum(a) > sum(b) ? a : b; return a < b ? a : b; // 利用pair自带的字典序 } const int maxnode = 1 << 21; // 修改以确保足够大 struct IntervalTree { int max_suffix[maxnode+1]; int max_prefix[maxnode+1]; Interval max_sub[maxnode+1]; int length; int p, v; int qL, qR; void init(int n) { length = n; //memset(minv, 0, sizeof(int) * (n + 5)); } //_query的封装 Interval query(int L, int R) { qL = L; qR = R; return _query(1, 1, length); } void build(int o, int L, int R) { if (L == R) { max_sub[o] = make_pair(L, L); max_prefix[o] = L; max_suffix[o] = L; } else { int M = L + (R-L)/2; int lc = 2*o, rc = 2*o+1; LL v1, v2; // 注意 sum 会溢出int,要用LL build(lc, L, M); build(rc, M+1, R); // 递推preffix v1 = sum(L, max_prefix[lc]); v2 = sum(L, max_prefix[rc]); //if(v1 == v2) max_prefix[o] = min(max_prefix[lc], max_prefix[rc]); //else max_prefix[o] = v1 > v2 ? max_prefix[lc] : max_prefix[rc]; max_prefix[o] = v1 >= v2 ? max_prefix[lc] : max_prefix[rc];// 因为要求字典序最小 // 递推suffix v1 = sum(max_suffix[lc], R); v2 = sum(max_suffix[rc], R); //if(v1 == v2) max_suffix[o] = min(max_suffix[lc], max_suffix[rc]); //else max_suffix[o] = v1 > v2 ? max_suffix[lc] : max_suffix[rc]; max_suffix[o] = v1 >= v2 ? max_suffix[lc] : max_suffix[rc]; max_sub[o] = better(max_sub[lc], max_sub[rc]); max_sub[o] = better(max_sub[o], make_pair(max_suffix[lc], max_prefix[rc])); } } Interval _query_preffix(int o, int L, int R) { if (max_prefix[o] <= qR) // L 是一定包含在查询区间中的 return make_pair(L, max_prefix[o]); int M = L + (R-L)/2; int lc = 2*o, rc = 2*o+1; if (qR <= M) return _query_preffix(lc, L, M); Interval i = _query_preffix(rc, M+1, R); i.first = L; return better(i, make_pair(L, max_prefix[lc])); } Interval _query_suffix(int o, int L, int R) { if (max_suffix[o] >= qL) return make_pair(max_suffix[o], R); int M = L + (R-L)/2; int lc = 2*o, rc = 2*o+1; if (qL > M) return _query_suffix(rc, M+1, R); Interval i = _query_suffix(lc, L, M); i.second = R; return better(i, make_pair(max_suffix[rc], R)); } Interval _query(int o, int L, int R) { if (qL <= L && qR >= R) return max_sub[o]; int M = L + (R-L)/2; int lc = 2*o, rc = 2*o + 1; if (qR <= M) return _query(lc, L, M); if (qL > M) return _query(rc, M+1, R); Interval suffix = _query_suffix(lc, L, M); // 左半的后缀和 Interval preffix = _query_preffix(rc, M+1, R); // 右半的前缀和 Interval ret = better(_query(lc, L, M), _query(rc, M+1, R)); ret = better(ret, make_pair(suffix.first, preffix.second)); // 和最大区间过中点的情况 return ret; } }; IntervalTree tree; int main() { int n, m; int tmp; int cases = 0; while(scanf("%d%d", &n, &m) != EOF) { prefix_sum[0] = 0; F(i, n) { scanf("%d",&tmp); prefix_sum[i+1] = prefix_sum[i] + tmp; } // build tree tree.init(n); tree.build(1, 1, n); printf("Case %d:\n", ++cases); F(i, m) { int l, r; scanf("%d%d",&l, &r); Interval interval = tree.query(l, r); printf("%d %d\n", interval.first, interval.second); } } return 0; }
相关文章推荐
- UVa 1400 "Ray, Pass me the dishes!"(区间最大连续数组和)
- UVaLive 3938 "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 Ray, Pass me the dishes!(线段树:复杂段查询)
- 线段树(1):点修改 (uva 1400 Ray,Pass me the Dishes)
- UVA-1400 Ray, Pass me the Dishes, LA 3938 , 线段树,区间查询
- UVALive 3938 Ray, Pass me the dishes! (动态最大连续和)
- LA3938 & UVA1400 - Ray, Pass me the dishes!(线段树)
- UVA 1400 "Ray, Pass me the dishes!" (线段树)
- UVA 1400 "Ray, Pass me the dishes!"(线段树)
- [线段树点修改]动态最大连续和(Ray,Pass me the Dishes, LA 3938)
- UVALive3938 "Ray, Pass me the dishes!" 线段树动态区间最大和
- uva 1400 - "Ray, Pass me the dishes!"(线段树)
- UVA 1400 1400 - "Ray, Pass me the dishes!"(线段树)
- uvalive 3938 - "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!"(线段树)