hdu5316區間最值問題(附帶題目意思詳解) 一次ac

T組數據

N個數字,M次操作

op=0:找出L-R區間內的最大‘值’

op=1:把a位置的數字換成b

對最大‘值’的定義:取區間內的最大子序列,需要保證子序列的下標爲奇偶交替的


用線段樹分別記錄每個區間的

.........s1.......奇數位開始,奇數位結束
.........s2.......奇數位開始,偶數爲結束
.........s3.......偶數位開始,偶數位結束
.........s4.......偶數位開始,奇數位結束


對每次詢問分別處理4種情況的最大值即可

此題乍一看比較麻煩, 筆者剛開始想到dp,但沒有思路,而此題又有很裸地線段樹特點,於是用線段樹做。此題與一般線段樹不同的是,節點上記錄的是幾個值

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=100010;
const ll INF=-1e9;
int n,m;
ll t,a[N];
typedef struct
{
    int left,right;
//.........s1.......奇數位開始,奇數位結束
//.........s2.......奇數位開始,偶數爲結束
//.........s3.......偶數位開始,偶數位結束
//.........s4.......偶數位開始,奇數位結束
    ll s1,s2,s3,s4;
}P;
P per[4*N];
typedef struct
{
    ll s1,s2,s3,s4;
}data;
ll MAX(ll a,int b)
{
    if(a>b)
        return a;
    return b;
}
ll MAX(ll a,ll b,ll c,ll d)
{
    ll m1=max(a,b),m2=max(c,d);
    return max(m1,m2);
}
void build(int id,ll left,ll right)
{
    per[id].left=left;
    per[id].right=right;
    if(left==right)
    {
        if(left&1)
        {
            per[id].s1=a[left];
            per[id].s2=INF;
            per[id].s3=INF;
            per[id].s4=INF;
        }
        else
        {
            per[id].s1=INF;
            per[id].s2=INF;
            per[id].s3=a[left];
            per[id].s4=INF;
        }
        return;
    }
    else
    {
        int mid=(left+right)>>1,len1=id<<1,len2=id<<1|1;
        build(len1,left,mid);
        build(len2,mid+1,right);
        ll as1,as2,as3,as4,bs1,bs2,bs3,bs4;
        as1=per[len1].s1;   as2=per[len1].s2;
        as3=per[len1].s3;   as4=per[len1].s4;
        bs1=per[len2].s1;   bs2=per[len2].s2;
        bs3=per[len2].s3;   bs4=per[len2].s4;
        per[id].s1=MAX(as1,bs1,as1+bs4,as2+bs1);
        per[id].s2=MAX(as2,bs2,as2+bs2,as1+bs3);
        per[id].s3=MAX(as3,bs3,as3+bs2,as4+bs3);
        per[id].s4=MAX(as4,bs4,as4+bs4,as3+bs1);
    }


}
void update(int id,ll a,ll b)
{//cout<<"a= "<<a<<" b= "<<b<<endl;
    if(per[id].left>a||per[id].right<a)
        return;
    if(per[id].left==per[id].right&&per[id].left==a)
    {//cout<<"updata= "<<a<<" b= "<<b<<endl;
        if(a&1)
            per[id].s1=b;
        else
            per[id].s3=b;
    }
    else
    {
        ll mid=(per[id].left+per[id].right)>>1;
        ll len1=id<<1,len2=len1+1;
        if(mid<a)
            update(len2,a,b);
        else
            if(mid>=a)
            update(len1,a,b);
            ll as1,as2,as3,as4,bs1,bs2,bs3,bs4;
        as1=per[len1].s1;   as2=per[len1].s2;
        as3=per[len1].s3;   as4=per[len1].s4;
        bs1=per[len2].s1;   bs2=per[len2].s2;
        bs3=per[len2].s3;   bs4=per[len2].s4;
        per[id].s1=MAX(as1,bs1,as1+bs4,as2+bs1);
        per[id].s2=MAX(as2,bs2,as2+bs2,as1+bs3);
        per[id].s3=MAX(as3,bs3,as3+bs2,as4+bs3);
        per[id].s4=MAX(as4,bs4,as4+bs4,as3+bs1);
    }
}
data query(int id,ll l,ll r)
{
    ll s;
    if(per[id].left==l&&per[id].right==r)
    {
        data da;
        da.s1=per[id].s1;   da.s2=per[id].s2;
        da.s3=per[id].s3;   da.s4=per[id].s4;
        return da;
    }
    if(per[id].left>r||per[id].right<l)
    {
        data da;
        da.s1=INF;   da.s2=INF;
        da.s3=INF;   da.s4=INF;
        return da;
    }
    ll mid=(per[id].left+per[id].right)>>1;
    ll len1=id<<1,len2=len1+1;
    if(r<=mid)
        return query(len1,l,r);
    else
        if(l>mid)
            return query(len2,l,r);
    else
        {
            data d1=query(len1,l,mid);
            data d2=query(len2,mid+1,r);
            data d3;
            d3.s1=MAX(d1.s1,d2.s1,d1.s1+d2.s4,d1.s2+d2.s1);
            d3.s2=MAX(d1.s2,d2.s2,d1.s1+d2.s3,d1.s2+d2.s2);
            d3.s3=MAX(d1.s3,d2.s3,d1.s3+d2.s2,d1.s4+d2.s3);
            d3.s4=MAX(d1.s4,d2.s4,d1.s3+d2.s1,d1.s4+d2.s4);
            return d3;
        }
}
int main()
{
    int i,j;
    ll l,r,k;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(i=1;i<=n;i++)
                scanf("%lld",&a[i]);
            build(1,1,n);
            for(i=0;i<m;i++)
            {
                cin>>k>>l>>r;
                if(k==0)
                {
                    data da=query(1,l,r);
                    ll mmax=MAX(da.s1,da.s2,da.s3,da.s4);
                    cout<<mmax<<endl;
                }
                if(k==1)
                {
                    update(1,l,r);
                    //for(i=1;i<=4*n;i++)
                }
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章