hdu 5316 Magician(2015多校第三場第1題)線段樹單點更新+區間合併

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5316

題意:給你n個點,m個操作,每次操作有3個整數t,a,b,t表示操作類型,當t=1時講a點的值改成b;當t=0時,查詢區間a,b之間最大的子序列和,這個子序列中的相鄰的元素的原來的下標奇偶性都不同。

思路:這道題難點就在查詢,其餘都是模板,而根據查詢,你只要分別把下一個區間的奇偶最大的情況分別比較,合併到上一個區間這樣可以構建一個每個節點存有區間中奇開頭偶開頭,奇結尾,偶結尾這些區間情況的樹。

代碼:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>

#define N 100005
#define LL __int64
#define INF 0x3f3f3f3f
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct node
{
	int l,r;
	LL jo,oo,oj,jj;
}seg[N<<4],aa;
LL ans;
void Push_Up(int rt)
{
    seg[rt].jj=max(max(seg[ls].jj+seg[rs].oj,seg[ls].jo+seg[rs].jj),max(seg[ls].jj,seg[rs].jj));
    seg[rt].oo=max(max(seg[ls].oo+seg[rs].jo,seg[ls].oj+seg[rs].oo),max(seg[ls].oo,seg[rs].oo));
    seg[rt].jo=max(max(seg[ls].jj+seg[rs].oo,seg[ls].jo+seg[rs].jo),max(seg[ls].jo,seg[rs].jo));
    seg[rt].oj=max(max(seg[ls].oo+seg[rs].jj,seg[ls].oj+seg[rs].oj),max(seg[ls].oj,seg[rs].oj));
}

void Build(int l,int r,int rt)
{
    seg[rt].l=l;
    seg[rt].r=r;
    if(l==r)
    {
        LL a;
        scanf("%I64d",&a);
        if(l&1)
        {
            seg[rt].jj=a;
            seg[rt].oo=-INF;
        }
        else
        {
            seg[rt].oo=a;
            seg[rt].jj=-INF;
        }
        seg[rt].jo=seg[rt].oj=-INF;
        return ;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    Push_Up(rt);
}

void Update(int p,int x,int rt)
{
    if(seg[rt].l==seg[rt].r&&seg[rt].l==p)
    {
        if(p&1)
            seg[rt].jj=x;
        else
            seg[rt].oo=x;
        return ;
    }
    int m=(seg[rt].l+seg[rt].r)>>1;
    if(p<=m)
        Update(p,x,ls);
    else
        Update(p,x,rs);
    Push_Up(rt);
}

void Get(node ll,node rr)
{
    aa.jj=max(max(ll.jj+rr.oj,ll.jo+rr.jj),max(ll.jj,rr.jj));
    aa.oo=max(max(ll.oo+rr.jo,ll.oj+rr.oo),max(ll.oo,rr.oo));
    aa.jo=max(max(ll.jj+rr.oo,ll.jo+rr.jo),max(ll.jo,rr.jo));
    aa.oj=max(max(ll.oo+rr.jj,ll.oj+rr.oj),max(ll.oj,rr.oj));
}

node Query(int l,int r,int rt)
{
    if(seg[rt].l==l&&seg[rt].r==r)
    {
        aa=seg[rt];
        ans=max(max(aa.jj,aa.jo),max(aa.oj,aa.oo));
        return seg[rt];
    }
    int m=(seg[rt].l+seg[rt].r)>>1;
    ans=0;
    if(r<=m)
        aa=Query(l,r,ls);
    else if(l>m)
        aa=Query(l,r,rs);
    else
    {
        node ll,rr;
        ll=Query(lson);
        rr=Query(rson);
        Get(ll,rr);
    }
    ans=max(max(aa.jj,aa.jo),max(aa.oj,aa.oo));
    return aa;
}

int main()
{
    int n,m,a,b,t,T;
	while(scanf("%d",&T)==1)
	{
	    while(T--)
        {
            scanf("%d%d",&n,&m);
            Build(1,n,1);
            while(m--)
            {
                scanf("%d%d%d",&t,&a,&b);
                if(t==1)
                    Update(a,b,1);
                else
                {
                    Query(a,b,1);
                    printf("%I64d\n",ans);
                }
            }
        }
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章