NYOJ 1068 ST(段树 为段更新+间隔总和)
2015-08-24 15:22
405 查看
ST
时间限制:1000 ms | 内存限制:65535 KB难度:1
描写叙述
“麻雀”lengdan用随机数生成了后台数据。可是笨笨的他被妹纸的问题给难住了。
。。
已知lengdan生成了N(1=<N<=10005)个随机整数,妹子对这些数可能有下面几种操作或询问:
1,A a b c 表示给区间a到b内每一个数都加上c。
2,S a b 表示输出区间a到b内的和。
3,Q a b 表示区间a到b内的奇数的个数;
为了使妹纸不口渴,所以我们决定妹纸的询问次数少一点。即(1=<M<=10000,M为询问次数)。
输入
多组測试数据。
每组測试数据第一行包括两个数N,M。表示N个整数,运行M次询问或操作。
紧接着一行输入N个整数,输入数据保证在int范围内。
接下来M行,每行输入一种操作。
输出
每次对于操作2和3。输出结果。
例子输入
5 5 1 2 3 4 5 Q 1 4 S 1 5 A 1 4 1 S 1 5 Q 2 5
例子输出
2 15 19 3
简单的线段树成段更新+区间求和,仅仅是附加了求区间内的奇数个数。由于之前没有写过线段树成段更新的题目,导致由于一条向下更新的语句忘记写,调了一个上午才发现错误。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int N = 10010; #define lson l, mid, root<<1 #define rson mid+1, r, root<<1|1 struct node { int l, r; LL sum, odd, add; }a[N<<2]; void PushUp(int root) { a[root].sum = a[root<<1].sum + a[root<<1|1].sum; a[root].odd = a[root<<1].odd + a[root<<1|1].odd; } void PushDown(int len, int root) { if(a[root].add) { a[root<<1].add += a[root].add; a[root<<1|1].add += a[root].add; a[root<<1].sum += LL(len - (len>>1)) * a[root].add; a[root<<1|1].sum += LL(len>>1) * a[root].add; if(a[root].add % 2 == 1) { a[root<<1].odd = len - (len>>1) - a[root<<1].odd; a[root<<1|1].odd = (len>>1) - a[root<<1|1].odd; } a[root].add = 0; } } void build_tree(int l, int r, int root) { a[root].l = l; a[root].r = r; a[root].add = 0; a[root].odd = 0; if(l == r) { scanf("%lld",&a[root].sum); if(a[root].sum % 2 == 1) a[root].odd = 1; return; } int mid = (l + r) >> 1; build_tree(lson); build_tree(rson); PushUp(root); } void update(int l, int r, int root, LL k) { if(l <= a[root].l && r >= a[root].r) { a[root].add += k; a[root].sum += LL(a[root].r - a[root].l + 1) * k; if(k % 2 == 1) a[root].odd = (a[root].r - a[root].l + 1) - a[root].odd; return; } PushDown(a[root].r - a[root].l + 1, root); int mid = (a[root].l + a[root].r) >> 1; if(l <= mid) update(l, r, root<<1, k); if(r > mid) update(l, r, root<<1|1, k); PushUp(root); } LL Query(int l, int r, int root, char ch) { if(l <= a[root].l && r >= a[root].r) { if(ch == 'Q') return a[root].odd; else if(ch == 'S') return a[root].sum; } PushDown(a[root].r - a[root].l + 1, root); LL ans = 0; int mid = (a[root].l + a[root].r) >> 1; if(l <= mid) ans += Query(l, r, root<<1, ch); if(r > mid) ans += Query(l, r, root<<1|1, ch); return ans; } int main() { int n, m, i, x, y; LL z; char ch[5]; while(~scanf("%d%d",&n,&m)) { build_tree(1, n, 1); while(m--) { scanf("%s",ch); if(ch[0] == 'A') { scanf("%d%d%lld",&x,&y,&z); update(x, y, 1, z); } else { scanf("%d%d",&x,&y); printf("%lld\n", Query(x, y, 1, ch[0])); } } } return 0; }
相关文章推荐
- vc++创建文件目录
- C# VS 面向对象基础(一)
- Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)
- lamp搭建
- 迭代器模式(Iterator)
- CSS 字体代码
- c++回调函数, caffe新版本新用法
- poj 1183 数学推导(反正切函数的应用)
- Think in Java之构造器的真正调用顺序
- 【最短路】【负圈可达点】【用while(!Q.empty())】【优先队列优化】【dij】
- 【准备工作—你做好了吗?】
- Easyui datagrid detailview使用简介
- 黑马程序员_Map双列集合
- C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器
- Linux内核动态加载模块
- Android时区及语言代码
- NGUI 不写一行代码实现翻拍效果
- Caliburn Micro Part 3: More About Events and Parameters
- git常用命令及技巧
- PAT 1063. Set Similarity (25)