1. 程式人生 > >[HDU 5316] Magician (線段樹+單點更新+區間詢問+區間合併)

[HDU 5316] Magician (線段樹+單點更新+區間詢問+區間合併)

HDU - 5316
給你一個長度為 N的序列,有 M個操作
0 a b: 詢問[a,b]區間內下標奇偶交替的序列的最大和
1 a b: 將 a位置的數改為 b

很顯然這是一個區間詢問,單點修改的線段樹
具體寫法就是區間合併的思想
首先奇偶交替的序列有四種情況:
1) 奇頭奇尾 (oo)
2) 奇頭偶尾 (oe)
3) 偶頭奇尾 (eo)
4) 偶頭偶尾 (ee)
然後小區間的序列合併到大區間的方式
就是四個量,左兒子各取最大,右兒子各取最大,跨越中間的各取最大(注意中間斷點是奇偶交替的)
最後就維護出答案了
詢問也是一樣的方式

#include <cstdio>
#include <iostream> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; typedef pair<int,int> Pii; typedef long long LL; typedef unsigned long long ULL; typedef
double DBL; typedef long double LDBL; #define MST(a,b) memset(a,b,sizeof(a)) #define CLR(a) MST(a,0) #define Pow2(a) (a*a) const int maxn=1e5+10; #ifdef LOCAL const LL INF=100; #else const LL INF=0x3f3f3f3f3f3f3f3fLL; #endif struct SegmentTree { struct node { int l,r; LL oo,oe,eo,ee; void
init(){oo=oe=eo=ee=-INF;} void pri(const char *a="\n"){printf("l:%d r:%d oo:%-4lld oe:%-4lld eo:%-4lld ee:%-4lld%s", l,r,oo,oe,eo,ee,a);} } *segt; SegmentTree(int size){segt=new node[4*size];CLR(segt);} ~SegmentTree(){delete []segt;} void build(int,int,int); void update(int,int,int); node query(int,int,int); void maintain(int); void combine(const node&,const node&,node&); void pushdown(int); }; int N,M; int inpt[maxn]; SegmentTree tree(maxn); int main() { int T; scanf("%d", &T); for(int ck=1; ck<=T; ck++) { scanf("%d%d", &N, &M); for(int i=1; i<=N; i++) scanf("%d", &inpt[i]); tree.build(1,1,N); for(int i=1; i<=M; i++) { int opt,a,b; scanf("%d%d%d", &opt, &a, &b); if(opt==0) { SegmentTree::node ans=tree.query(1,a,b); printf("%lld\n", max(max(ans.oo,ans.oe), max(ans.eo,ans.ee))); } if(opt==1) tree.update(1,a,b); } } return 0; } void SegmentTree::build(int np,int nl,int nr) { node &now=segt[np]; now.l=nl; now.r=nr; now.oo=now.oe=now.eo=now.ee=-INF; if(nl==nr){maintain(np);/*now.pri("\n");*/return;} int mid=(nl+nr)>>1; build(np*2,nl,mid); build(np*2+1,mid+1,nr); maintain(np); // now.pri("\n"); } void SegmentTree::update(int np,int ql,int val) { node &now=segt[np]; if(now.l==now.r) { inpt[now.l]=val; maintain(np); return; } int mid=(now.l+now.r)>>1; if(ql<=mid) update(np*2,ql,val); else update(np*2+1,ql,val); maintain(np); } SegmentTree::node SegmentTree::query(int np,int ql,int qr) { node &now=segt[np]; // now.pri();system("pause"); if(ql<=now.l&&now.r<=qr) { return now; } int mid=(now.l+now.r)>>1; node ansl,ansr,ans; ansl.init();ansr.init(); if(ql<=mid) ansl=query(np*2,ql,qr); if(qr>mid) ansr=query(np*2+1,ql,qr); combine(ansl,ansr,ans); return ans; } void SegmentTree::maintain(int np) { node &now=segt[np]; if(now.l==now.r) { if(now.l&1) now.oo=inpt[now.l]; else now.ee=inpt[now.l]; return; } node &lson=segt[np*2];node &rson=segt[np*2+1]; combine(lson,rson,now); } void SegmentTree::combine(const SegmentTree::node &u, const SegmentTree::node &v, SegmentTree::node& res) { res.oo=max( max(u.oo, v.oo), max(u.oo+v.eo, u.oe+v.oo)); res.oe=max( max(u.oe, v.oe), max(u.oo+v.ee, u.oe+v.oe)); res.eo=max( max(u.eo, v.eo), max(u.eo+v.eo, u.ee+v.oo)); res.ee=max( max(u.ee, v.ee), max(u.eo+v.ee, u.ee+v.oe)); }