hdu 5316 Magician 线段树维护最大值
题目链接:Magician
题意:
给你一个长度为n的序列v,你需要对这个序列进行m次操作,操作一共有两种,输入格式为
type a b
1、如果type==0,你就需要输出[a,b]区间内的美丽序列中所有元素的和,要使得这个值尽可能大
2、如果type==1,你就需要把a位置的元素值改为b
区间[a,b]的美丽序列就是va,va+1...vb。你需要从中取出任意个元素,这些元素的位置必须是奇偶交替
例如给你一个序列1,2,3,4,5,6,7
你取出来的美丽序列就有可能使1,2,3,4,5,6,7或者1,4,5,6,7或者2,5,6,7
题解:
我们使用线段树,如果type==1的时候就修改就可以了。对于type==0的情况。我们可以维护四个值,分别是区间[a,b]内的美丽序列:
从一个偶数位置开始,到一个奇数位置截至,我们使用ab来代替
从一个奇数位置开始,到一个奇数位置截至,我们使用bb来代替
从一个偶数位置开始,到一个偶数位置截至,我们使用aa来代替
从一个奇数位置开始,到一个偶数位置截至,我们使用ba来代替
对于线段树上一个节点维护的值,我们把这个节点称为a,把它的左右节点称为b,c
a.ab=max(b.aa+c.bb,b.ab+c.ab); 如果左右子树合并
a.ab=max(a.ab,max(b.ab,c.ab)); 如果左右子树不合并
其他四个值的维护也是这样
代码:
#include <map> #include <set> #include <list> #include <queue> #include <deque> #include <cmath> #include <stack> #include <vector> #include <bitset> #include <cstdio> #include <string> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 1e5+10; const int INF = 0x3f3f3f3f; const double PI = 3.1415926; const long long N = 1000006; const double eps = 1e-10; typedef long long ll; #define qmh(x) ask() #define mt(A, B) memset(A, B, sizeof(A)) #define lson L, mid, rt<<1 #define rson mid + 1, R, rt<<1|1 #define ls rt<<1 #define rs rt<<1|1 #define SIS std::ios::sync_with_stdiget_mod_new(z-x)o(false), cin.tie(0), cout.tie(0) #define pll pair<long long, long long> #define lowbit(abcd) (abcd & (-abcd)) #define max(a, b) ((a > b) ? (a) : (b)) #define min(a, b) ((a < b) ? (a) : (b)) struct node { ll aa,bb,ab,ba; void Clear() { aa=bb=ab=ba=-INF; } } tree[400009],result; int arr[100009]; void Merge(node &a,node b,node c) { a.aa=max(b.ab+c.aa,b.aa+c.ba); a.aa=max(a.aa,max(b.aa,c.aa)); a.bb=max(b.ba+c.bb,b.bb+c.ab); a.bb=max(a.bb,max(b.bb,c.bb)); a.ab=max(b.aa+c.bb,b.ab+c.ab); a.ab=max(a.ab,max(b.ab,c.ab)); a.ba=max(b.bb+c.aa,b.ba+c.ba); a.ba=max(a.ba,max(b.ba,c.ba)); } void build(int rt,int L,int R) { if(L==R) { tree[rt].Clear(); if(L&1) tree[rt].aa=arr[L]; else tree[rt].bb=arr[L]; return ; } int mid=(L+R)>>1; build(rt<<1,L,mid),build(rt<<1|1,mid+1,R); Merge(tree[rt],tree[rt<<1],tree[rt<<1|1]); } void update(int rt,int L,int R,int pos,int val) { if(L==R) { tree[rt].Clear(); if(L&1) tree[rt].aa=val; else tree[rt].bb=val; return ; } int mid=(L+R)>>1; if(pos<=mid) update(rt<<1,L,mid,pos,val); else update(rt<<1|1,mid+1,R,pos,val); Merge(tree[rt],tree[rt<<1],tree[rt<<1|1]); } void query(int rt,int L,int R,int LL,int RR) { if(L>=LL&&R<=RR) { Merge(result,result,tree[rt]); return ; } int mid=(L+R)>>1; if(mid>=LL) query(rt<<1,L,mid,LL,RR); if(RR>mid) query(rt<<1|1,mid+1,R,LL,RR); } int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&arr[i]); build(1,1,n); while(m--) { int type,l,r; scanf("%d%d%d",&type,&l,&r); if(type==1) update(1,1,n,l,r); else { result.Clear(); query(1,1,n,l,r); printf("%lld\n",max(max(result.aa,result.bb),max(result.ab,result.ba))); } } } return 0; }