zl程序教程

您现在的位置是:首页 >  其它

当前栏目

hdu 5316 Magician 线段树维护最大值

HDU 维护 线段 最大值
2023-09-27 14:26:02 时间

题目链接:Magician

 

题意:

给你一个长度为n的序列v,你需要对这个序列进行m次操作,操作一共有两种,输入格式为

type a b

1、如果type==0,你就需要输出[a,b]区间内的美丽序列中所有元素的和,要使得这个值尽可能大

2、如果type==1,你就需要把a位置的元素值改为b

 

区间[a,b]的美丽序列就是va,va+1...vb。你需要从中取出任意个元素,这些元素的位置必须是奇偶交替

例如给你一个序列1,2,3,4,5,6,7

你取出来的美丽序列就有可能使1,2,3,4,5,6,7或者1,4,5,6,7或者2,5,6,7

 

题解:

我们使用线段树,如果type==1的时候就修改就可以了。对于type==0的情况。我们可以维护四个值,分别是区间[a,b]内的美丽序列:

从一个偶数位置开始,到一个奇数位置截至,我们使用ab来代替

从一个奇数位置开始,到一个奇数位置截至,我们使用bb来代替

从一个偶数位置开始,到一个偶数位置截至,我们使用aa来代替

从一个奇数位置开始,到一个偶数位置截至,我们使用ba来代替

 

对于线段树上一个节点维护的值,我们把这个节点称为a,把它的左右节点称为b,c

 

a.ab=max(b.aa+c.bb,b.ab+c.ab);   如果左右子树合并
a.ab=max(a.ab,max(b.ab,c.ab));   如果左右子树不合并

 

 

其他四个值的维护也是这样

 

代码:

 

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
const double PI = 3.1415926;
const long long N = 1000006;
const double eps = 1e-10;
typedef long long ll;
#define qmh(x) ask()
#define mt(A, B) memset(A, B, sizeof(A))
#define lson L, mid, rt<<1
#define rson mid + 1, R, rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
#define SIS std::ios::sync_with_stdiget_mod_new(z-x)o(false), cin.tie(0), cout.tie(0)
#define pll pair<long long, long long>
#define lowbit(abcd) (abcd & (-abcd))
#define max(a, b) ((a > b) ? (a) : (b))
#define min(a, b) ((a < b) ? (a) : (b))
struct node
{
    ll aa,bb,ab,ba;
    void Clear()
    {
        aa=bb=ab=ba=-INF;
    }
} tree[400009],result;
int arr[100009];

void Merge(node &a,node b,node c)
{
    a.aa=max(b.ab+c.aa,b.aa+c.ba);
    a.aa=max(a.aa,max(b.aa,c.aa));
    a.bb=max(b.ba+c.bb,b.bb+c.ab);
    a.bb=max(a.bb,max(b.bb,c.bb));
    a.ab=max(b.aa+c.bb,b.ab+c.ab);
    a.ab=max(a.ab,max(b.ab,c.ab));
    a.ba=max(b.bb+c.aa,b.ba+c.ba);
    a.ba=max(a.ba,max(b.ba,c.ba));
}

void build(int rt,int L,int R)
{
    if(L==R)
    {
        tree[rt].Clear();
        if(L&1) tree[rt].aa=arr[L];
        else tree[rt].bb=arr[L];
        return ;
    }
    int mid=(L+R)>>1;
    build(rt<<1,L,mid),build(rt<<1|1,mid+1,R);
    Merge(tree[rt],tree[rt<<1],tree[rt<<1|1]);
}

void update(int rt,int L,int R,int pos,int val)
{
    if(L==R)
    {
        tree[rt].Clear();
        if(L&1) tree[rt].aa=val;
        else tree[rt].bb=val;
        return ;
    }
    int mid=(L+R)>>1;
    if(pos<=mid) update(rt<<1,L,mid,pos,val);
    else update(rt<<1|1,mid+1,R,pos,val);
    Merge(tree[rt],tree[rt<<1],tree[rt<<1|1]);
}

void query(int rt,int L,int R,int LL,int RR)
{
    if(L>=LL&&R<=RR)
    {
        Merge(result,result,tree[rt]);
        return ;
    }
    int mid=(L+R)>>1;
    if(mid>=LL) query(rt<<1,L,mid,LL,RR);
    if(RR>mid) query(rt<<1|1,mid+1,R,LL,RR);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) scanf("%d",&arr[i]);
        build(1,1,n);
        while(m--)
        {
            int type,l,r;
            scanf("%d%d%d",&type,&l,&r);
            if(type==1) update(1,1,n,l,r);
            else
            {
                result.Clear();
                query(1,1,n,l,r);
                printf("%lld\n",max(max(result.aa,result.bb),max(result.ab,result.ba)));
            }
        }
    }
    return 0;
}