poj2750 PottedFlower(线段树的环状操作)

题目:Potted Flower
大意:该你一个换环,求环上的最大连续的和(如果最大和包含所有数,要求减去最小的一个)。
思路:这道题的思路并不难,需要在线段树里维护区间的最大和,最小和(应为是环状的,所以答案有可能是总和减去最小和),然后需要用一个区间左边的最大最小,右边的最大最小来维护区间的最大和最小和。这道题的解法就是这样。

代码奉上

#include<cstdio>
#include<algorithm>
using namespace std;
#define M(i) ((t[(i)].l + t[i].r) >> 1)
const int MAXN = 1e5 + 5;
const int INF = 1e9;
struct node
{
    int l,r,lmx,rmx,lmn,rmn,sum,mx,mn;
}t[MAXN << 2];
int n, p[MAXN], m;
void build(int i, int l, int r)
{
    t[i].l = l;
    t[i].r = r;
    t[i].lmx = t[i].rmx = t[i].mx = -INF;
    t[i].lmn = t[i].rmn = t[i].mn = INF;
    if(l == r) {p[l] = i; return;}
    build(i<<1, l, M(i));
    build(i<<1|1, M(i)+1, r);
}
int max(int a,int b,int c)
{
    return max(a,max(b,c));
}
int min(int a,int b,int c)
{
    return min(a,min(b,c));
}
void upd(int pos, int v)
{
    int i = p[pos];
    t[i].lmx = t[i].rmx = t[i].sum = t[i].lmn = t[i].rmn = t[i].mx = t[i].mn = v;
    i >>= 1;
    while(i)
    {
        t[i].lmx = max(t[i<<1].lmx, t[i<<1].sum + t[i<<1|1].lmx);
        t[i].lmn = min(t[i<<1].lmn, t[i<<1].sum + t[i<<1|1].lmn);
        t[i].rmx = max(t[i<<1|1].rmx, t[i<<1|1].sum + t[i<<1].rmx);
        t[i].rmn = min(t[i<<1|1].rmn, t[i<<1|1].sum + t[i<<1].rmn);
        t[i].sum = t[i<<1].sum + t[i<<1|1].sum;
        t[i].mx = max(t[i<<1].mx,t[i<<1].rmx+t[i<<1|1].lmx,t[i<<1|1].mx);
        t[i].mn = min(t[i<<1].mn,t[i<<1].rmn+t[i<<1|1].lmn,t[i<<1|1].mn);
        i >>= 1;
    }
}
int main()
{
    int t1, t2;
    scanf("%d", &n);
    build(1, 1, n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &t1);
        upd(i, t1);
    }
    scanf("%d", &m);
    for(int i = 1; i <= m; i++)
    {
        scanf("%d%d", &t1, &t2);
        upd(t1, t2);
        if(t[1].mx == t[1].sum && t[1].sum > 0)
            printf("%d\n",t[1].sum - t[1].mn);
        else
            printf("%d\n",max(t[1].mx,t[1].sum - t[1].mn));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值