Hdu 5316 Magician (线段树区间合并)
来源:互联网 发布:淘宝天天特价规则 编辑:程序博客网 时间:2024/05/16 07:50
解析:关键是处理奇偶的问题。
正如官方题解所说,本题的子序列实际上可以根据起始数值下标的奇偶性分为四类。
对于每一类,如果你熟悉线段树,那么可以看出这个问题是可以进行区间合并的。
即如果知道一个区间[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|1using 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;}
0 0
- HDU 5316 Magician(线段树区间合并)
- HDU 5316 Magician(线段树区间合并入门)
- hdu 5316 Magician(线段树区间合并)
- HDU 5316 Magician(线段树 区间合并)
- Hdu 5316 Magician (线段树区间合并)
- [HDU 5316] Magician (线段树+单点更新+区间询问+区间合并)
- HDU5316 Magician (线段树区间合并)
- hdu 5316 Magician(2015多校第三场第1题)线段树单点更新+区间合并
- 多校第三场 1001 hdu 5316 Magician( 区间合并线段树)
- HDU 5316 Magician(线段树区间合并, 子序列最值 多校2015啊)
- HDU5316 Magician 线段树区间合并
- hdu5316 Magician(线段树区间合并)
- hdu5316 Magician(线段树区间合并)
- HDU 5316 Magician(线段树)
- hdu 5316 Magician(线段树)
- HDU 5316 Magician(线段树)
- hdu 5316 Magician (线段树)
- 【HDU 5316】Magician(线段树)
- Java IO最详解
- 二叉树线索化
- 欢迎使用CSDN-markdown编辑器
- RPC框架-Thrift的使用
- sublime 插件
- Hdu 5316 Magician (线段树区间合并)
- mac terminal终端打开指定文件夹 当前文件夹打开terminal
- Android学习笔记02——OKHttp网络框架01
- 欢迎使用CSDN-markdown编辑器
- PAT乙级练习题B1038. 统计同成绩学生
- ATOM基础教程一ATOM代码片段snippets(7)
- yii 框架用swiftmailer 发送邮件
- 约瑟夫环问题
- ccnuacm