Hdu 5316 Magician (線段樹區間合併)

解析:關鍵是處理奇偶的問題。

正如官方題解所說,本題的子序列實際上可以根據起始數值下標的奇偶性分爲四類。
對於每一類,如果你熟悉線段樹,那麼可以看出這個問題是可以進行區間合併的。
即如果知道一個區間[L, R]兩個子區間 [L,mid], [mid+1,R]的信息,我們可以推出[L,R][L,R]的信息。
維護四個值,表示起點終點的下標的奇偶性。

[code]:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;

struct Node{
    LL v0,v1,v2,v3;
    Node(){}
    Node(LL v0,LL v1,LL v2,LL v3):v0(v0),v1(v1),v2(v2),v3(v3){}
    void init(LL v0,LL v1,LL v2,LL v3){
        this->v0 = v0;this->v1 = v1;
        this->v2 = v2;this->v3 = v3;
    }
    LL answer(){
        return max(max(v0,v1),max(v2,v3));
    }
};

void build(int,int,int) __attribute__((optimize("O3")));
void update(int,int,int,int,int) __attribute__((optimize("O3")));
Node query(int,int,int,int,int) __attribute__((optimize("O3")));


inline bool read(int &ret){
    char c;int sgn;
    if(c = getchar(),c==EOF) return 0;
    while(c != '-'&&(c<'0'||c>'9')) c=getchar();
    sgn = (c=='-')?-1:1;
    ret = (c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}

int n,m,a[maxn];
LL C[4*maxn][4];

void push_up(int rt){
    C[rt][0] = max(C[rt<<1][0],max(C[rt<<1|1][0],max(C[rt<<1][0]+C[rt<<1|1][2],C[rt<<1][1]+C[rt<<1|1][0])));
    C[rt][1] = max(C[rt<<1][1],max(C[rt<<1|1][1],max(C[rt<<1][1]+C[rt<<1|1][1],C[rt<<1][0]+C[rt<<1|1][3])));
    C[rt][2] = max(C[rt<<1][2],max(C[rt<<1|1][2],max(C[rt<<1][2]+C[rt<<1|1][2],C[rt<<1][3]+C[rt<<1|1][0])));
    C[rt][3] = max(C[rt<<1][3],max(C[rt<<1|1][3],max(C[rt<<1][2]+C[rt<<1|1][3],C[rt<<1][3]+C[rt<<1|1][1])));
}

void build(int l,int r,int rt){
    if(l == r){
        if(l&1) C[rt][0] = a[l],C[rt][3] = -INF;
        else C[rt][0] = -INF,C[rt][3] = a[l];
        C[rt][1] = C[rt][2] = -INF;
        return;
    }
    int mid = (l+r)>>1;
    build(lson);build(rson);
    push_up(rt);
}

void update(int k,int x,int l,int r,int rt){
    if(l == r){
        if(k&1) C[rt][0] = x;
        else C[rt][3] = x;
        return;
    }
    int mid = (l+r)>>1;
    if(k <= mid) update(k,x,lson);
    else update(k,x,rson);
    push_up(rt);
}

Node query(int a,int b,int l,int r,int rt){
    if(a<=l&&r<=b) return Node(C[rt][0],C[rt][1],C[rt][2],C[rt][3]);
    int mid = (l+r)>>1;
    if(b<=mid) return query(a,b,lson);
    else if(a > mid) return query(a,b,rson);
    else{
        Node ls,rs,s;
        ls = query(a,b,lson);rs = query(a,b,rson);
        s.v0 = max(max(ls.v0,rs.v0),max(ls.v0+rs.v2,ls.v1+rs.v0));
        s.v1 = max(max(ls.v1,rs.v1),max(ls.v1+rs.v1,ls.v0+rs.v3));
        s.v2 = max(max(ls.v2,rs.v2),max(ls.v2+rs.v2,ls.v3+rs.v0));
        s.v3 = max(max(ls.v3,rs.v3),max(ls.v2+rs.v3,ls.v3+rs.v1));
        return s;
    }
}


int main(){
    int i,j,cas,op,l,r;
    scanf("%d",&cas);
    while(cas--){
        read(n);read(m);
        for(i = 1;i <= n;i++) read(a[i]);
        build(1,n,1);
        while(m--){
            read(op);read(l);read(r);
            if(op==0){
                printf("%I64d\n",query(l,r,1,n,1).answer());
            }else{
                update(l,r,1,n,1);
            }
        }
    }

    return 0;
}


發佈了219 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章