您的位置:首页 > 其它

POJ 2750 Potted Flower(线段树 + DP)

2015-08-10 21:47 295 查看
题目链接:http://poj.org/problem?id=2750

题意:给出N个数成环,再给M个操作,每次操作会改变某个数的数值,问每次更新完成后区间的最大和是多少,该区间不能是整个区间

思路:将环从某点切开看成一段序列,对于一个区间而言,如过所选序列不包括断点,那么直接求区间最大连续和smax即可,如果包括断点,那么答案则为max(smax, sum - smin),sum为区间总和,smin为区间最小连续和。

对于更新可以用线段树维护以下信息,sum为区间和,lmax为区间从左至右最大连续和,rmax为区间从右至左最大连续和,smax为区间最大连续和(最小连续和也同样处理)

故而有转移:

tr[rt].lmax = max(tr[ls].lmax, tr[ls].sum + tr[rs].lmax);       

tr[rt].rmax = max(tr[rs].rmax, tr[rs].sum + tr[ls].rmax);

tr[rt].smax = max(max(tr[ls].smax, tr[rs].smax), tr[ls].rmax + tr[rs].lmax);        

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <climits>
#include <functional>
#include <deque>
#include <ctime>

#define ls rt << 1
#define rs rt << 1 | 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;

const int maxn = 100010;

struct segtree
{
int sum;
int lmax, rmax, smax;
int lmin, rmin, smin;
} tr[maxn << 2];

void pushup(int rt)
{
tr[rt].sum = tr[ls].sum + tr[rs].sum;

tr[rt].lmax = max(tr[ls].lmax, tr[ls].sum + tr[rs].lmax);
tr[rt].rmax = max(tr[rs].rmax, tr[rs].sum + tr[ls].rmax);
tr[rt].smax = max(max(tr[ls].smax, tr[rs].smax), tr[ls].rmax + tr[rs].lmax);

tr[rt].lmin = min(tr[ls].lmin, tr[ls].sum + tr[rs].lmin);
tr[rt].rmin = min(tr[rs].rmin, tr[rs].sum + tr[ls].rmin);
tr[rt].smin = min(min(tr[ls].smin, tr[rs].smin), tr[ls].rmin + tr[rs].lmin);
}

void build(int l, int r, int rt)
{
if (l == r)
{
scanf("%d", &tr[rt].sum);
tr[rt].lmax = tr[rt].rmax = tr[rt].smax = tr[rt].sum;
tr[rt].lmin = tr[rt].rmin = tr[rt].smin = tr[rt].sum;
return ;
}

int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}

void update(int p, int c, int l, int r, int rt)
{
if (l == r)
{
tr[rt].sum = c;
tr[rt].lmax = tr[rt].rmax = tr[rt].smax = c;
tr[rt].lmin = tr[rt].rmin = tr[rt].smin = c;
return ;
}

int mid = (l + r) >> 1;
if (p <= mid)
update(p, c, lson);
else
update(p, c, rson);
pushup(rt);
}

int main()
{
int n;
while (~scanf("%d", &n))
{
build(1, n, 1);

int m;
scanf("%d", &m);
while (m--)
{
int p, c;
scanf("%d%d", &p, &c);
update(p, c, 1, n, 1);

if (tr[1].sum == tr[1].smax)
printf("%d\n", tr[1].sum - tr[1].smin);
else
printf("%d\n", max(tr[1].smax, tr[1].sum - tr[1].smin));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: