nyoj1068 ST 线段树
来源:互联网 发布:社交网络的利弊 英文 编辑:程序博客网 时间:2024/05/08 23:13
题目链接
线段树查询区间和以及区间奇数个数。
区间和很好求,很快就写好了,区间奇数个数写起来麻烦一点,除了查询的时候需要lazy操作,更新的时候也需要lazy操作。
直接上代码:
#include<stdio.h>#include<string.h>#define ll long long#define maxn 10010struct stu{ ll l,r,mid,lazysum,odd,sum,lazyodd; } w[maxn<<2];void build(ll l,ll r,ll tr) //建树{ w[tr].mid=(l+r)>>1; w[tr].l=l,w[tr].r=r,w[tr].odd=0,w[tr].lazysum=0,w[tr].lazyodd=0; if(l==r) scanf("%lld",&w[tr].sum),w[tr].odd=w[tr].sum&1; else { build(l,w[tr].mid,tr<<1),build(w[tr].mid+1,r,tr<<1|1); w[tr].sum=w[tr<<1].sum+w[tr<<1|1].sum; w[tr].odd=w[tr<<1].odd+w[tr<<1|1].odd; }}void update(ll x,ll y,ll z,ll tr) //更新{ if(w[tr].lazyodd&&w[tr].l!=w[tr].r) //若有lazyodd,且不是叶子节点 { w[tr<<1].lazyodd^=1,w[tr<<1|1].lazyodd^=1; //子节点的lazyodd若为0,就变成1,若为1,就变成0 w[tr<<1].odd=w[tr<<1].r-w[tr<<1].l+1-w[tr<<1].odd;//无论子节点的lazyodd是否为1,均更新子节点的odd个数 w[tr<<1|1].odd=w[tr<<1|1].r-w[tr<<1|1].l+1-w[tr<<1|1].odd; w[tr].lazyodd=0; //向子节点传递lazyodd后,清零 } if(w[tr].l==x&&w[tr].r==y) { w[tr].lazysum+=z; //更新lazysum w[tr].sum+=(y-x+1)*z; if(z&1) w[tr].lazyodd^=1,w[tr].odd=w[tr].r-w[tr].l+1-w[tr].odd; //若要加的数为奇数,无论lazyodd是否为奇数,均更新tr区间奇数个数 return ; } else if(y<=w[tr].mid) update(x,y,z,tr<<1); else if(x>w[tr].mid) update(x,y,z,tr<<1|1); else update(x,w[tr].mid,z,tr<<1),update(w[tr].mid+1,y,z,tr<<1|1); w[tr].sum+=(y-x+1)*z; //更新sum if(z&1) w[tr].odd=w[tr<<1].odd+w[tr<<1|1].odd; //更新线段树中包含(x,y)区间的区间奇数个数}ll query_odd(ll x,ll y,ll tr){ if(w[tr].lazyodd&&w[tr].l!=w[tr].r) //和update类似 { w[tr<<1].lazyodd^=1,w[tr<<1|1].lazyodd^=1; w[tr<<1].odd=w[tr<<1].r-w[tr<<1].l+1-w[tr<<1].odd; w[tr<<1|1].odd=w[tr<<1|1].r-w[tr<<1|1].l+1-w[tr<<1|1].odd; w[tr].lazyodd=0; } if(w[tr].l==x&&w[tr].r==y) return w[tr].odd; else if(w[tr].mid>=y) return query_odd(x,y,tr<<1); else if(w[tr].mid<x) return query_odd(x,y,tr<<1|1); else return query_odd(x,w[tr].mid,tr<<1)+query_odd(w[tr].mid+1,y,tr<<1|1);}ll query_sum(ll x,ll y,ll tr){ if(w[tr].lazysum&&w[tr].l!=w[tr].r) //sum的lazy操作 { w[tr<<1].lazysum+=w[tr].lazysum; w[tr<<1|1].lazysum+=w[tr].lazysum; w[tr<<1].sum+=(w[tr<<1].r-w[tr<<1].l+1)*w[tr].lazysum; w[tr<<1|1].sum+=(w[tr<<1|1].r-w[tr<<1|1].l+1)*w[tr].lazysum; w[tr].lazysum=0; } if(w[tr].l==x&&w[tr].r==y) return w[tr].sum; else if(y<=w[tr].mid) return query_sum(x,y,tr<<1); else if(x>w[tr].mid) return query_sum(x,y,tr<<1|1); else return query_sum(x,w[tr].mid,tr<<1)+query_sum(w[tr].mid+1,y,tr<<1|1);}int main(){ ll n,m,i,j,x,z,y; while(scanf("%lld%lld",&n,&m)!=EOF) { char c; build(1,n,1); while(m--) { scanf("\n%c",&c); scanf("%lld%lld",&x,&y); if(c=='S') printf("%lld\n",query_sum(x,y,1)); else if(c=='Q') printf("%lld\n",query_odd(x,y,1)); else { scanf("%lld",&z); update(x,y,z,1); } } } return 0;}
0 0
- nyoj1068 ST 线段树
- RMQ问题 (st+线段树)
- POJ 3264 线段树 ST
- POJ-3264 RMQ 线段树与ST
- poj 3264 Balanced Lineup ST+线段树
- POJ_3368_Frequent values_线段树/ST稀疏表
- RMQ(ST 与 线段树)eg poj3264
- POJ3264 Balanced Lineup 线段树|ST表
- [Noi2010] D1T2 超级钢琴 (ST表 线段树 主席树)
- POJ2823 Sliding Window(线段树 ST算法 优先队列)
- poj 3264RMQ问题(线段树,ST算法)
- POJ3264 Balanced Lineup 线段树 RMQ ST算法应用
- Balanced Lineup-POJ - 3264-RMQ线段树/st表
- POJ 3264 Balanced Lineup(st或者线段树)
- nyoj 1068 ST【线段树】求和&&奇数个数
- 【数据结构与算法】RMQ+ST及线段树
- POJ3264 RMQ问题 裸 线段树 OR ST算法
- 【POJ】3264 - Balanced Lineup(RMQ - ST算法 || 线段树)
- 【Android - MD】之NavigationView的使用
- [LeetCode]Remove Duplicates from Sorted List II
- 企业面试题&&strlen与sizeof的区别
- 2016年中国大学生程序设计竞赛(合肥)-重现赛(感谢安徽大学) A E H I
- 7种排序算法的介绍(常用)
- nyoj1068 ST 线段树
- 无线信号穿墙能力
- 二进制的源码 补码 反码
- 快速排序
- python之sys.argv 用法解析
- HDU 1565 方格取数(1) 二分图最大点权独立集
- LeetCode 28Implement strStr() 寻找子字符串的下标的位置
- 【C语言】每瓶汽水1元,两个空瓶可以置换一瓶汽水,现在有20元,最多能喝多少瓶汽水。
- Lightoj 1414 - February 29 (闰年统计,容斥定理)