您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: