題目鏈接:點擊查看
題目大意:給出長度為 n 的數列 a ,接下來進行 m 次操作,每次操作分為兩種類型:
0 l r:詢問區間 [ l , r ] 內的最長子序列之和,要求相鄰兩個位置的下標奇偶性不同1 pos val:修改 pos 位置的數字為 val
題目分析:需要用到區間合并,因為下標奇偶性不同,所以在合并的時候,一共只有四種情況:奇奇,奇偶,偶奇,偶偶,直接分情況維護最大值就好了
代碼:
?
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;typedef long long LL;typedef unsigned long long ull;const LL inf=0x3f3f3f3f3f3f3f3f;const int N=1e5+100;struct Node
{int l,r;LL oo,jj,oj,jo;
}tree[N<<2];void pushup(int k)
{Node &a=tree[k<<1],&b=tree[k<<1|1];tree[k].jj=max(max(a.jj,b.jj),max(a.jj+b.oj,a.jo+b.jj));tree[k].oo=max(max(a.oo,b.oo),max(a.oo+b.jo,a.oj+b.oo));tree[k].jo=max(max(a.jo,b.jo),max(a.jj+b.oo,a.jo+b.jo));tree[k].oj=max(max(a.oj,b.oj),max(a.oo+b.jj,a.oj+b.oj));
}void init(int k,LL val,int pos)
{tree[k].oo=tree[k].jj=tree[k].oj=tree[k].jo=-inf;if(pos&1)tree[k].jj=val;elsetree[k].oo=val;
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;if(l==r){LL val;scanf("%lld",&val);init(k,val,l);return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}void change(int k,int pos,LL val)
{if(tree[k].l==tree[k].r){init(k,val,tree[k].l);return;}int mid=tree[k].l+tree[k].r>>1;if(pos<=mid)change(k<<1,pos,val);elsechange(k<<1|1,pos,val);pushup(k);
}Node query(int k,int l,int r)
{if(tree[k].l>=l&&tree[k].r<=r)return tree[k];int mid=tree[k].l+tree[k].r>>1;if(r<=mid)return query(k<<1,l,r);else if(l>mid)return query(k<<1|1,l,r);else{Node a=query(k<<1,l,r),b=query(k<<1|1,l,r),ans;ans.jj=max(max(a.jj,b.jj),max(a.jj+b.oj,a.jo+b.jj));ans.oo=max(max(a.oo,b.oo),max(a.oo+b.jo,a.oj+b.oo));ans.jo=max(max(a.jo,b.jo),max(a.jj+b.oo,a.jo+b.jo));ans.oj=max(max(a.oj,b.oj),max(a.oo+b.jj,a.oj+b.oj));return ans;}
}int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);int w;cin>>w;while(w--){int n,m;scanf("%d%d",&n,&m);build(1,1,n);while(m--){int op;scanf("%d",&op);if(op==1){int pos;LL val;scanf("%d%lld",&pos,&val);change(1,pos,val);}else if(op==0){int l,r;scanf("%d%d",&l,&r);Node t=query(1,l,r);printf("%lld\n",max(max(t.jj,t.oo),max(t.oj,t.jo)));}}}return 0;
}
?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生
總結
以上是生活随笔為你收集整理的HDU - 5316 Magician(线段树区间合并)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。