HDU 5316 Magician(线段树)
2015-07-29 16:40
204 查看
题意:有两种操作,查询操作求区间内的最大子序列,需要保证子序列的下标为奇偶交替的,还有单点修改操作。
思路:对于一个合法的子序列,只有可能是以奇奇,奇偶,偶奇,偶偶为开头和结尾。
线段树维护区间内的这四个值,重载加法运算符简化编程。
题意:有两种操作,查询操作求区间内的最大子序列,需要保证子序列的下标为奇偶交替的,还有单点修改操作。
思路:对于一个合法的子序列,只有可能是以奇奇,奇偶,偶奇,偶偶为开头和结尾。
线段树维护区间内的这四个值,重载加法运算符简化编程。
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #define eps 1e-6 #define LL long long using namespace std; const int maxn = 200000 + 100; const LL INF = 1e14; int a[maxn]; struct Node { LL jj, jo, oo, oj; } nodes[2*maxn]; Node operator + (const Node& A, const Node& B) { Node t; t.jj = max(max(A.jj, B.jj), max(A.jo+B.jj, A.jj+B.oj)); t.jo = max(max(A.jo, B.jo), max(A.jo+B.jo, A.jj+B.oo)); t.oo = max(max(A.oo, B.oo), max(A.oo+B.jo, A.oj+B.oo)); t.oj = max(max(A.oj, B.oj), max(A.oo+B.jj, A.oj+B.oj)); return t; } struct seg_tree { void update(int o, int L, int R, int p, LL v) { int M = (R+L) >> 1; if(L == R) { if(L&1) nodes[o].jj = v; else nodes[o].oo = v; } else { if(p <= M) update(o*2, L, M, p, v); else update(o*2+1, M+1, R, p, v); nodes[o] = nodes[2*o] + nodes[2*o+1]; } } Node query(int o, int L, int R, int ql, int qr) { int M = (L+R) >> 1; LL ans = -INF; if(ql <= L && qr >= R) return nodes[o]; if(ql > M) return query(2*o+1, M+1, R, ql, qr); else if(qr <= M) return query(2*o, L, M, ql, qr); else return query(2*o, L, M, ql, qr) + query(2*o+1, M+1, R, ql, qr); } LL Ans(int o, int L, int R, int ql, int qr) { Node t = query(o, L, R, ql, qr); return max( max(t.jj, t.jo), max(t.oo, t.oj) ); } void built_tree(int o, int L, int R) { int M = (L+R) >> 1; if(L == R) { if(L&1) { nodes[o].jj = (LL)a[L]; nodes[o].jo = nodes[o].oo = nodes[o].oj = -INF; } else { nodes[o].oo = (LL)a[L]; nodes[o].jo = nodes[o].jj = nodes[o].oj = -INF; } } else { built_tree(o*2, L, M); built_tree(o*2+1, M+1, R); nodes[o] = nodes[2*o] + nodes[2*o+1]; } } } st; int main() { // freopen("input.txt", "r", stdin); int t; cin >> t; int n, m; while(t--) { cin >> n >> m; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); st.built_tree(1, 1, n); while(m--) { int t1, t2, t3; scanf("%d%d%d", &t1, &t2, &t3); if(!t1) cout << st.Ans(1, 1, n, t2, t3) << endl; else st.update(1, 1, n, t2, (LL)t3); } } return 0; }
相关文章推荐
- Qt Creator 窗体控件自适应窗口大小布局
- [转]JAVA正则表达式 Pattern和Matcher
- FIND的使用方法
- SQL Server 2012 SEQUENCE 使用
- 使用dubbo2.5出现A child container failed during start
- 2015 多校联赛 ——HDU5316(线段树)
- Web访问原理-从输入URL到页面加载完成的过程中都发生了什么事情?
- 2015 多校联赛 ——HDU5316(线段树)
- adt 开发环境下直接查询sqlite数据库工具
- 实现外网访问局域网内的SVN——花生壳+visiualSVN实现外网访问局域网内的SVN(三)
- angularJS中include的页面的ng-model不能实时存取
- SQL Server 数据库优化文章
- 你必须知道的简单的位操作技巧
- ELK系列--justniffer0.5.12安装报错解决方法
- 北大ACM试题分类 - 实时更新我所有的解题报告链接
- JAVA垃圾收集器与内存分配策略详解
- Android Fragment 基本了解
- Andriod 单元测试—InstrumentationTestCase
- Heap
- 单链表中去除重复数据