您的位置:首页 > 其它

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