题目链接:
点击打开链接
题目大意:
给出一个数组,定义一个美丽子序列,这个子序列当中相邻的数的原位置的奇偶性不同,那么问某个区间的的最大的子序列的和是多少
题目分析:
线段树的区间合并模板题,维护四个值,分别是奇偶,偶奇,奇奇,偶偶,代表每个区间开始的一个数的奇偶性和结束一个数的奇偶性,保存最大的值,然后每次进行区间合并的时候
每个性质的区间满足如下的合并规则
奇偶被如下区间更新:
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 ); } } } }