多校第三场 1001 hdu 5316 Magician( 区间合并线段树)

题目链接:

点击打开链接

题目大意:

给出一个数组,定义一个美丽子序列,这个子序列当中相邻的数的原位置的奇偶性不同,那么问某个区间的的最大的子序列的和是多少

题目分析:

线段树的区间合并模板题,维护四个值,分别是奇偶,偶奇,奇奇,偶偶,代表每个区间开始的一个数的奇偶性和结束一个数的奇偶性,保存最大的值,然后每次进行区间合并的时候

每个性质的区间满足如下的合并规则

奇偶被如下区间更新:

1.左奇偶

2.右奇偶

3.奇偶+奇偶

4.奇奇+偶偶

偶奇被如下区间更新:

1.左偶奇

2.右偶奇

3.偶偶+奇奇

4.偶奇+偶奇

奇奇被如下区间更新:

1.左奇奇

2.右奇奇

3.奇奇+偶奇

4.奇偶+奇奇

偶偶被如下区间更新:

1.左偶偶

2.右偶偶

3.偶奇+偶偶

4.偶偶+奇偶

下面是我聚挫无比的代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 100007

using namespace std;

const long long INF = 1e16+10;

typedef long long LL;

struct Tree
{
    int l,r;
    LL jiou;
    LL ouji;
    LL jiji;
    LL ouou;
    int mark[5];
}tree[MAX<<2];

int a[MAX];

void push_up ( int u )
{
    int id1 = u<<1 , id2 = u<<1|1;
    tree[u].jiji = -INF;
    memset ( tree[u].mark , 0 , sizeof ( tree[u].mark ));
    //jiji
    if ( tree[id1].mark[3] )
    {
        tree[u].mark[3] = 1;
        tree[u].jiji = max ( tree[u].jiji , tree[id1].jiji );
    }
    if ( tree[id2].mark[3] )
    {
        tree[u].mark[3] = 1;
        tree[u].jiji = max ( tree[u].jiji , tree[id2].jiji );
    }
    if ( tree[id1].mark[1] && tree[id2].mark[3] )
    {
        tree[u].mark[3] = 1;
        tree[u].jiji =  max ( tree[id1].jiou + tree[id2].jiji , tree[u].jiji );
    }
    if (tree[id1].mark[3] && tree[id2].mark[2] )
    {
        tree[u].mark[3] = 1;
        tree[u].jiji = max ( tree[u].jiji , tree[id1].jiji + tree[id2].ouji );
    }
    //jiou
    tree[u].jiou = -INF;
    if ( tree[id1].mark[1] )
    {
        tree[u].mark[1] = 1;
        tree[u].jiou = max ( tree[u].jiou , tree[id1].jiou );
    }
    if ( tree[id2].mark[1] )
    {
        tree[u].mark[1] = 1;
        tree[u].jiou = max ( tree[u].jiou , tree[id2].jiou );
    }
    if ( tree[id1].mark[1] && tree[id2].mark[1] )
    {
        tree[u].mark[1] = 1;
        tree[u].jiou = max ( tree[id1].jiou+tree[id2].jiou , tree[u].jiou );
    }
    if ( tree[id1].mark[3] && tree[id2].mark[4] )
    {
        tree[u].mark[1] = 1;
        tree[u].jiou = max ( tree[id1].jiji+tree[id2].ouou , tree[u].jiou );
    }
    //ouji
    tree[u].ouji = -INF;
    if ( tree[id1].mark[2] )
    {
        tree[u].mark[2] = 1;
        tree[u].ouji = max (tree[id1].ouji , tree[u].ouji );
    }
    if ( tree[id2].mark[2] )
    {
        tree[u].mark[2] = 1;
        tree[u].ouji = max ( tree[id2].ouji , tree[u].ouji );
    }
    if ( tree[id1].mark[2] && tree[id2].mark[2] )
    {
        tree[u].mark[2] = 1;
        tree[u].ouji = max ( tree[id1].ouji + tree[id2].ouji , tree[u].ouji );
    }
    if ( tree[id1].mark[4] && tree[id2].mark[3] )
    {
        tree[u].mark[2] = 1;
        tree[u].ouji = max ( tree[id1].ouou + tree[id2].jiji , tree[u].ouji );
    }
    //ouou
    tree[u].ouou = -INF;
    if ( tree[id1].mark[4] )
    {
        tree[u].mark[4] = 1;
        tree[u].ouou = max ( tree[u].ouou , tree[id1].ouou );
    }
    if ( tree[id2].mark[4] )
    {
        tree[u].mark[4] = 1;
        tree[u].ouou = max ( tree[u].ouou , tree[id2].ouou );
    }
    if ( tree[id1].mark[2] && tree[id2].mark[4] )
    {
        tree[u].mark[4] = 1;
        tree[u].ouou = max ( tree[u].ouou , tree[id1].ouji + tree[id2].ouou );
    }
    if ( tree[id1].mark[4] && tree[id2].mark[1] )
    {
        tree[u].mark[4] = 1;
        tree[u].ouou = max ( tree[u].ouou , tree[id1].ouou + tree[id2].jiou );
    }
}

void build ( int u , int l , int r )
{
    tree[u].l = l;
    tree[u].r = r;
    memset ( tree[u].mark , 0 , sizeof ( tree[u].mark ));
    if ( l == r )
    {
        if ( l%2 == 0 )
        {
            tree[u].ouou = a[l];
            tree[u].mark[4] = 1;
        }
        else
        {
            tree[u].jiji = a[l];
            tree[u].mark[3] = 1;
        }
        return;
    }
    int mid = l+r>>1;
    build ( u<<1 , l , mid );
    build ( u<<1|1 , mid+1 , r );
    push_up ( u );
}

void update ( int u , int x , int v )
{
    int l = tree[u].l;
    int r = tree[u].r;
    int mid = l+r>>1;
    if ( l == r )
    {
        if ( l%2 == 0 )
        {
            tree[u].mark[4] = 1;
            tree[u].ouou = v;
        }
        else
        {
            tree[u].mark[3] = 1;
            tree[u].jiji = v;
        }
        return;
    }
    if ( x > mid ) update ( u<<1|1 , x , v );
    else update ( u<<1 , x , v );
    push_up ( u );
}

/*LL query ( int u , int left , int right )
{
    LL ret = -INF;
    int l = tree[u].l , r = tree[u].r;
    if ( left <= l && r <= right )
    {
        ret = max ( ret , tree[u].jiji );
        ret = max ( ret , tree[u].jiou );
        ret = max ( ret , tree[u].ouji );
        ret = max ( ret , tree[u].ouou );
        return ret;
    }
    int mid = l+r>>1;
    if ( left <= mid && right >= l )
        ret = max ( ret , query ( u<<1 , left , right ));
    if ( left <= r && right > mid )
        ret = max ( ret , query ( u<<1|1 , left , right ));
    return ret;
}*/

struct Node
{
    LL jiou,ouji,jiji,ouou;
    int mark[5];
    Node ( )
    {
        jiou = ouji = jiji = ouou = -INF;
        memset ( mark , 0 , sizeof ( mark ));
    };
    Node ( LL a5 , LL b2 , LL c2 , LL d2 , int a1 , int a2 , int a3 , int a4 )
    {
        jiou = a5;
        ouji = b2;
        jiji = c2;
        ouou = d2;
        mark[1] = a1;
        mark[2] = a2;
        mark[3] = a3;
        mark[4] = a4;
    }
};

Node query ( int u , int left , int right )
{
    int l = tree[u].l , r = tree[u].r;
    int mid = l + r >>1;
    Node ret;
    if ( left <= l && r <= right )
    {
        Node a = Node ( tree[u].jiou , tree[u].ouji , tree[u].jiji , tree[u].ouou,
              tree[u].mark[1] , tree[u].mark[2] , tree[u].mark[3] , tree[u].mark[4] );
        return a;
    }
    Node temp1,temp2;
    int used1=0,used2=0;
    if ( left <= mid && right >= l )
    {
        used1 = 1;
        temp1 = query ( u<<1 , left , right );
    }
    if ( left <= r && right > mid )
    {
        used2 = 1;
        temp2 = query ( u<<1|1 , left ,right );
    }
    if ( used1 && used2 )
    {
        if ( temp1.mark[3] )
        {
            ret.mark[3] = 1;
            ret.jiji = max ( ret.jiji , temp1.jiji );
        }
        if ( temp2.mark[3] )
        {
            ret.mark[3] = 1;
            ret.jiji = max ( ret.jiji , temp2.jiji );
        }
        if ( temp1.mark[1] && temp2.mark[3] )
        {
            ret.mark[3] = 1;
            ret.jiji =  max ( temp1.jiou + temp2.jiji , ret.jiji );
        }
        if ( temp1.mark[3] && temp2.mark[2] )
        {
            ret.mark[3] = 1;
            ret.jiji = max ( ret.jiji , temp1.jiji + temp2.ouji );
        }
        //jiou
        ret.jiou = -INF;
        if ( temp1.mark[1] )
        {
            ret.mark[1] = 1;
            ret.jiou = max ( ret.jiou , temp1.jiou );
        }
        if ( temp2.mark[1] )
        {
            ret.mark[1] = 1;
            ret.jiou = max ( ret.jiou , temp2.jiou );
        }
        if ( temp1.mark[1] && temp2.mark[1] )
        {
            ret.mark[1] = 1;
            ret.jiou = max ( temp1.jiou+temp2.jiou , ret.jiou );
        }
        if ( temp1.mark[3] && temp2.mark[4] )
        {
            ret.mark[1] = 1;
            ret.jiou = max ( temp1.jiji+temp2.ouou , ret.jiou );
        }
        //ouji
        ret.ouji = -INF;
        if ( temp1.mark[2] )
        {
            ret.mark[2] = 1;
            ret.ouji = max ( ret.ouji , temp1.ouji );
        }
        if ( temp2.mark[2] )
        {
            ret.mark[2] = 1;
            ret.ouji = max ( temp2.ouji , ret.ouji );
        }
        if ( temp1.mark[2] && temp2.mark[2] )
        {
            ret.mark[2] = 1;
            ret.ouji = max ( temp1.ouji + temp2.ouji , ret.ouji );
        }
        if ( temp1.mark[4] && temp2.mark[3] )
        {
            ret.mark[2] = 1;
            ret.ouji = max ( temp1.ouou + temp2.jiji , ret.ouji );
        }
        //ouou
        ret.ouou = -INF;
        if ( temp1.mark[4] )
        {
            ret.mark[4] = 1;
            ret.ouou = max ( ret.ouou , temp1.ouou );
        }
        if ( temp2.mark[4] )
        {
            ret.mark[4] = 1;
            ret.ouou = max ( ret.ouou , temp2.ouou );
        }
        if ( temp1.mark[2] && temp2.mark[4] )
        {
            ret.mark[4] = 1;
            ret.ouou = max ( ret.ouou , temp1.ouji + temp2.ouou );
        }
        if ( temp1.mark[4] && temp2.mark[1] )
        {
            ret.mark[4] = 1;
            ret.ouou = max ( ret.ouou , temp1.ouou + temp2.jiou );
        }
        return ret;
    }
    else if ( used1 )
    {
        return temp1;
    }
    else if ( used2 )
    {
        return temp2;
    }
    else return Node();
}

int t,n,q;

int main ( )
{
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d%d" , &n , &q );
        for ( int i = 1 ; i <= n ; i++ )
            scanf ( "%d" , &a[i] );
        build ( 1 , 1 , n );
        int f,x,y;
        while ( q-- )
        {
            scanf ( "%d%d%d" , &f , &x , &y );
            if ( f )
            {
                update ( 1 , x , y  );
            }
            else
            {
                LL ans = -INF;
                Node temp = query ( 1 , x , y );
                if ( temp.mark[1] )
                    ans = max ( ans , temp.jiou );
                if ( temp.mark[2] )
                    ans = max ( ans , temp.ouji );
                if ( temp.mark[3] )
                    ans = max ( ans , temp.jiji );
                if ( temp.mark[4] )
                    ans = max ( ans , temp.ouou );
                printf ( "%I64d\n" , ans );
            }
        }
    }
}


你可能感兴趣的:(C++,线段树,区间合并)