HDU 5316 Magician

题意:给你一个数列,然后要有两种操作。操作1 x y 代表把数列的第x个数字改成y

    操作0 x y 代表在a[x]....a[y]间找到一个beautiful 子序列的和最大

beautiful 子序列就是相邻的两个数在原来的数列的位置的奇偶性不一样

如a[1],a[4],a[5]就是,但a[2],a[4],就不是,因为2、4的奇偶性一样。

思路:线段树,用一个结构体去保存某段的beautiful序列的最大和

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<math.h>
#include<string>
using namespace std;
#pragma comment (linker, "/STACK:1024000000,1024000000")
typedef long long ll;
const int N = 100005;
const ll INF = 100000000000000;
struct node{
	ll v[2][2];			//v[0][1]  代表偶数位开头,奇数位结尾的beautiful序列的最大和
	ll vmax(){
		ll temp = -INF;
		for(int i = 0; i < 2; i++){
			for(int j = 0; j < 2; j++){
				temp = max(v[i][j], temp);
			}
		}
		return temp;
	}
}t[N<<2];
int n,Q,k;
void pushup(int rt){
	for(int i = 0; i < 2; i++){
		for(int j = 0; j < 2; j++){
			t[rt].v[i][j] = max(t[rt<<1].v[i][j], t[rt<<1|1].v[i][j]);
			t[rt].v[i][j] = max(t[rt].v[i][j], t[rt<<1].v[i][j^1] + t[rt<<1|1].v[j][j]);
			t[rt].v[i][j] = max(t[rt].v[i][j], t[rt<<1].v[i][j] + t[rt<<1|1].v[j^1][j]);
			//t[rt].v[i][j] = max(t[rt].v[i][j], 0LL);	//此处被坑了,子序列不能不取啊,就是就算是负数也要取,本以为负数就不取,就是0了
		}
	}
}
void update(int rt,int l,int r,int x,int val){
    if(l==r){
        if(x&1)t[rt].v[1][1] = val;
        else t[rt].v[0][0] = val;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)update(rt<<1, l, mid, x, val);
    else update(rt<<1|1, mid+1, r, x, val);
	pushup(rt);
}
node query(int rt,int l,int r,int x,int y){
    if(x<=l&&r<=y){
        return t[rt];
    }
    int mid=(l+r)>>1;
    node ans1, ans2, ret;
    bool flag1 = false, flag2 = false;
    if(x <= mid){
        ans1 = query(rt<<1, l, mid, x, y);
        flag1 = true;
    }
    if(y > mid){
        ans2 = query(rt<<1|1, mid+1, r, x, y);
        flag2 = true;
    }
    if(!flag1&&flag2){
		return ans2;
    }
    else if(!flag2&&flag1){
		return ans1;
    }
    else if(flag1 && flag2){
		for(int i = 0; i < 2; i++){
			for(int j = 0; j < 2; j++){
				ret.v[i][j] = max(ans1.v[i][j], ans2.v[i][j]);
				ret.v[i][j] = max(ret.v[i][j], ans1.v[i][j^1] + ans2.v[j][j]);
				ret.v[i][j] = max(ret.v[i][j], ans1.v[i][j] + ans2.v[j^1][j]);
				//ret.v[i][j] = max(ret.v[i][j], 0LL);
			}
		}
		return ret;
    }
}
void build(int rt, int l, int r){
	for(int i = 0; i < 2; i++)
		for(int j = 0; j < 2; j++)t[rt].v[i][j] = -INF;
	if(l == r){
		ll x;
		scanf("%I64d",&x);
		if(l&1)t[rt].v[1][1] = x;
		else t[rt].v[0][0] = x;
		return ;
	}
	int mid = (l+r)>>1;
	build(rt<<1, l, mid);
	build(rt<<1|1, mid+1,r);
	pushup(rt);
}
void work(){
    //freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
		k=0;
        scanf("%d%d",&n,&Q);
        build(1,1,n);
        while(Q--){
            int u,x,y;
            scanf("%d%d%d",&u,&x,&y);
            if(u == 0){
                node ans = query(1,1,n,x,y);
                printf("%I64d\n",ans.vmax());
            }
            else {
                update(1,1,n,x,y);
            }
        }
    }
}
int main(){
    work();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值