UESTC 1598 加帕里公园的friends 线段树区间合并

加帕里公园的friends

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 131072/131072KB (Java/Others)


Submit  Status
我还有很多话想和她说,还有很多地方想和她去,把Kaban酱还给我!——Sabaru




薮猫酱为了从天蓝怪手里拯救小包,必须发现天蓝怪们的弱点所在。
具体来说,n只天蓝怪组成了一个序列A,每一只有一个战斗力数值Ai,
之后会发生m个事件,事件共有两种类型,有可能是
1、薮猫酱给你一个区间[a,b],要你输出max{Ap+Ap+1+…+Aq}(a≤p≤q≤b)

2、第pos只天蓝怪的战斗力变成了X


Input

第一行是两个整数n、m,
第二行包含n个整数A1,A2,…,An,
接下来m行,每行三个整数,可能是
1ab,代表薮猫酱的一次询问;
2posX,代表某只天蓝怪战斗力的变化。


Output

对于每次询问,单独输出一行,代表答案。


Sample input and output

Sample Input Sample Output
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
2

-1


Hint

1≤n≤500000,
1≤m≤100000,
−1000≤Ai≤1000,
1≤a≤b≤n,
1≤pos≤n,

−1000≤X≤1000


Source

17暑假前集训-数据结构专题 By AutSky_JadeK

2017 UESTC Training for Data Structures

UESTC 1598 加帕里公园的friends


My Solution

题意:单点更新,区间查询最大子区间和。


线段树区间合并
每个节点维护四元组
int sum[4*MAXN], suml[4*MAXN], sumr[4*MAXN], ans[4*MAXN];
sum[Ind]表示该区间的和,suml[Ind]描述该区间从左端点开始的最大连续和,
sumr[Ind]表示从该区间右端点结束的最大连续和,ans[Ind]表示该区间的最大子区间和。
每次pushup的时候,刷新这四元组,
ans[Ind] = max(max(ans[Ind<<1], ans[Ind<<1|1]), sumr[Ind<<1] + suml[Ind<<1|1]);
suml[Ind] = max(suml[Ind<<1], sum[Ind<<1] + suml[Ind<<1|1]);
sumr[Ind] = max(sumr[Ind<<1|1], sumr[Ind<<1] + sum[Ind<<1|1]);
sum[Ind] = sum[Ind<<1] + sum[Ind<<1|1];
查询的时候,可以建立4个全局int findans, lans, rans, sumans;
每次查询到该最小区间即if(a <= l && r <= b)的时候刷新这个全局的四元组,
这样就不需要给查询函数设定返回值了,写起来比较方便,
即直接对该查询区间分成的子区间进行合并,具体见代码。
复杂度 O(nlogn)


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 5e5 + 8;
const int INF = -2e9+8;

int sum[4*MAXN], suml[4*MAXN], sumr[4*MAXN], ans[4*MAXN];
int findans, lans, rans, sumans;
int sz;
inline void pushdown(int Ind)
{
    ;
}
inline void pushup(int Ind)
{
    ans[Ind] = max(max(ans[Ind<<1], ans[Ind<<1|1]), sumr[Ind<<1] + suml[Ind<<1|1]);
    suml[Ind] = max(suml[Ind<<1], sum[Ind<<1] + suml[Ind<<1|1]);
    sumr[Ind] = max(sumr[Ind<<1|1], sumr[Ind<<1] + sum[Ind<<1|1]);
    sum[Ind] = sum[Ind<<1] + sum[Ind<<1|1];
}
inline void _Query(int a, int b, int l, int r, int Ind){
    if(a <= l && r <= b){
        if(findans == INF){
            findans = ans[Ind];
            lans = suml[Ind];
            rans = sumr[Ind];
            sumans = sum[Ind];
            return;
        }
        findans = max(max(findans, ans[Ind]), rans + suml[Ind]);
        lans = max(lans, sumans + suml[Ind]);
        rans = max(sumr[Ind], rans + sum[Ind]);
        sumans = sumans + sum[Ind];
        return;
    }
    int mid = (l + r) >> 1;
    if(a <= mid) { _Query(a, b, l, mid, Ind<<1); }
    if(b > mid) { _Query(a, b, mid + 1, r, Ind<<1|1);}
}
inline void _Modify(int a, int b, int l, int r, int Ind, int d){
    if(a == l && b == r){
        sum[Ind] = suml[Ind] = sumr[Ind] = ans[Ind] = d;
        return;
    }
    int mid = (l + r) >> 1;
    if(a <= mid){ _Modify(a, b, l, mid, Ind<<1, d); }
    if(b > mid){ _Modify(a, b, mid + 1, r,Ind<<1|1, d); }
    pushup(Ind);
}

inline void Query(int a, int b) {return _Query(a, b, 1, sz, 1);}
inline void Modify(int a, int b, int d){return _Modify(a, b, 1, sz, 1, d);}

int main()
{
    #ifdef LOCAL
    freopen("g.txt", "r", stdin);
    //freopen("g.out", "w", stdout);
    int T = 1;
    while(T--){
    #endif // LOCAL
    //ios::sync_with_stdio(false); cin.tie(0);

    int n, m, i, x, t, l, r;
    scanf("%d%d", &n, &m);
    sz = n;
    for(i = 1; i <= n; i++){
        scanf("%d", &x);
        Modify(i, i, x);
    }

    while(m--){
        scanf("%d%d%d", &t, &l, &r);
        if(t == 1){
            findans = lans = rans = sumans = INF;
            Query(l, r);
            printf("%d\n", findans);
        }
        else{
            Modify(l, l, r);
        }
    }

    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}


  Thank you!




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值