您的位置:首页 > 产品设计 > UI/UE

SPOJ 1043 Can you answer these queries I

2012-04-18 12:50 267 查看
SPOJ_1043

今天顿时发现原来GSS系列一共有7道题,这个是其中的一道,只要在网址那改一下GGS*就可以找到其他的题目了。

这个题目可以用线段树去做,一个可行的思路就是计算出三个标记mc[](当前区间内最大的连续子串和),lc[](从当前区间左端点开始向右的最大的连续子串和),rc[](从当前区间右端点开始的向左的最大的连续子串和)。

查询的时候利用这三个标记进行计算就可以了。

#include<stdio.h>
#include<string.h>
#define MAXD 50010
int N, A[MAXD], mc[4 * MAXD], lc[4 * MAXD], rc[4 * MAXD];
int getmax(int x, int y)
{
return x > y ? x : y;
}
void update(int cur, int x, int y)
{
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
mc[cur] = getmax(mc[ls], mc[rs]);
mc[cur] = getmax(mc[cur], rc[ls] + lc[rs]);
lc[cur] = getmax(lc[ls], A[mid] - A[x - 1] + lc[rs]);
rc[cur] = getmax(rc[rs], A[y] - A[mid] + rc[ls]);
}
void build(int cur, int x, int y)
{
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
if(x == y)
{
mc[cur] = lc[cur] = rc[cur] = A[x] - A[x - 1];
return ;
}
build(ls, x, mid);
build(rs, mid + 1, y);
update(cur, x, y);
}
void init()
{
int i;
A[0] = 0;
for(i = 1; i <= N; i ++)
{
scanf("%d", &A[i]);
A[i] = A[i - 1] + A[i];
}
build(1, 1, N);
}
int query(int cur, int x, int y, int s, int t, int flag, int &ans)
{
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1;
if(x >= s && y <= t)
{
ans = getmax(ans, mc[cur]);
return flag == -1 ? lc[cur] : rc[cur];
}
if(mid >= t)
return query(ls, x, mid, s, t, -1, ans);
else if(mid + 1 <= s)
return query(rs, mid + 1, y, s, t, 1, ans);
else
{
int ln, rn;
ln = query(ls, x, mid, s, t, 1, ans);
rn = query(rs, mid + 1, y, s, t, -1, ans);
ans = getmax(ans, ln + rn);
if(flag == -1)
return getmax(lc[ls], A[mid] - A[x - 1] + rn);
else
return getmax(rc[rs], A[y] - A[mid] + ln);
}
}
void solve()
{
int i, Q, x, y, ans;
scanf("%d", &Q);
for(i = 0; i < Q; i ++)
{
scanf("%d%d", &x, &y);
ans = A[x] - A[x - 1];
query(1, 1, N, x, y, -1, ans);
printf("%d\n", ans);
}
}
int main()
{
while(scanf("%d", &N) == 1)
{
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: