码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5316(2015多校3)--Magician(线段树+dp)

时间:2015-07-28 21:06:18      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:点击打开链接

题目大意:给出n个数,m次操作,有两种操作,0 l r 询问[l,r]内的一个序列最大和为多少,要求该序列的相邻的位置奇偶性不同,可以不连续;1 k x将第k个位置的数换位x

因为只要求奇偶性不同,所以一个序列的最大值有四种情况,偶数开始偶数结束,偶数开始奇数结束,奇数开始偶数奇数,奇数开始奇数结束。可以用一个数组表示,0表示偶数,1表示奇数,那么a[0][0],a[0][1],a[1][0],a[1][1]就能表示这四种情况了,查询[l,r]用线段树维护一下这四个值,注意在合并的时候的全部情况

dp[rt].a[i][j] = max(dp[rt<<1].a[i][j],dp[rt<<1|1].a[i][j]) 

dp[rt].a[i][j] = max(dp[rt].a[i][j],dp[rt<<1].a[i][0]+dp[rt<<1|1].a[1][j]) ;
dp[rt].a[i][j] = max(dp[rt].a[i][j],dp[rt<<1].a[i][1]+dp[rt<<1|1].a[0][j]) ;

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std ;
#define LL __int64
#define root 1,n,1
#define int_rt int l,int r,int rt
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define maxn 100010
struct node{
    LL a[2][2] ;
}dp[maxn<<2] , p , q ;
void push_up(int rt) {
    int i , j ;
    for(i = 0 ; i < 2 ; i++){
        for(j = 0 ; j < 2 ; j++) {
            dp[rt].a[i][j] = max(dp[rt<<1].a[i][j],dp[rt<<1|1].a[i][j]) ;
            dp[rt].a[i][j] = max(dp[rt].a[i][j],dp[rt<<1].a[i][0]+dp[rt<<1|1].a[1][j]) ;
            dp[rt].a[i][j] = max(dp[rt].a[i][j],dp[rt<<1].a[i][1]+dp[rt<<1|1].a[0][j]) ;
        }
    }
    return ;
}
void create(int_rt) {
    if( l == r ) {
        LL x ;
        scanf("%I64d", &x) ;
        dp[rt].a[0][0] = dp[rt].a[0][1] = dp[rt].a[1][0] = dp[rt].a[1][1] = -(LL)1e16 ;
        dp[rt].a[l%2][l%2] = x ;
        return ;
    }
    create(lson) ;
    create(rson) ;
    push_up(rt) ;
}
void update(int k,LL x,int_rt) {
    if( l == r ) {
        dp[rt].a[0][0] = dp[rt].a[0][1] = dp[rt].a[1][0] = dp[rt].a[1][1] = -(LL)1e16 ;
        dp[rt].a[l%2][l%2] = x ;
        return ;
    }
    int mid = (l+r)/2 ;
    if(k <= mid) update(k,x,lson) ;
    else update(k,x,rson) ;
    push_up(rt) ;
}
node query(int ll,int rr,int_rt) {
    if( ll <= l && rr >= r ){
        return dp[rt] ;
    }
    int i , j , mid = (l+r)/2 ;
    node s1 , s2 , temp ;
    s1.a[0][0] = s1.a[0][1] = s1.a[1][0] = s1.a[1][1] = -(LL)1e16 ;
    s2.a[0][0] = s2.a[0][1] = s2.a[1][0] = s2.a[1][1] = -(LL)1e16 ;
    if( ll <= mid ) s1 = query(ll,rr,lson) ;
    if( rr > mid ) s2 = query(ll,rr,rson) ;
    for(i = 0 ; i < 2 ; i++){
        for(j = 0 ; j < 2 ; j++) {
            temp.a[i][j] = max(s1.a[i][j],s2.a[i][j]) ;
            temp.a[i][j] = max(temp.a[i][j],s1.a[i][0]+s2.a[1][j]) ;
            temp.a[i][j] = max(temp.a[i][j],s1.a[i][1]+s2.a[0][j]) ;
        }
    }
    return temp ;
}
int main() {
    int t , n , m , i , j ;
    int k , l , r ;
    LL max1 , x ;
    scanf("%d", &t) ;
    while( t-- ) {
        scanf("%d %d", &n, &m) ;
        create(root) ;
        while( m-- ) {
            scanf("%d", &k) ;
            if( !k ) {
                scanf("%d %d", &l,&r) ;
                p = query(l,r,root) ;
                max1 = -(LL)1e16 ;
                for(i = 0 ; i < 2 ; i++)
                    for(j = 0 ; j < 2 ; j++)
                        max1 = max(max1,p.a[i][j]) ;
                printf("%I64d\n", max1) ;
            }
            else {
                scanf("%d %I64d", &k, &x) ;
                update(k,x,root) ;

            }
        }
    }
    return 0 ;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu5316(2015多校3)--Magician(线段树+dp)

标签:

原文地址:http://blog.csdn.net/winddreams/article/details/47110857

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!